React v16 vừa mới phát hành một vài giờ trước (Yay !!), chính thức hỗ trợ Portal
.
Cổng là gì? Vì nó đã ở đó bao lâu?
Cổng cung cấp cách thứ nhất để đưa trẻ em vào nút DOM tồn tại bên ngoài phân cấp DOM của thành phần gốc.
Portal
không phải là khái niệm mới trong cộng đồng phản ứng. Nhiều thư viện có sẵn hỗ trợ loại chức năng này. ví dụ: react-portal và react-gateway.
Điều gì sẽ xảy ra khi hiển thị bất kỳ ứng dụng phản ứng nào?
Nói chung, khi hiển thị bất kỳ ứng dụng React nào, một phần tử DOM duy nhất được sử dụng để hiển thị toàn bộ cây React.
class HelloReact extends React.Component {
render() {
return (
<h1>Hello React</h1>
);
}
}
ReactDOM.render(<HelloReact />, document.getElementById('root'));
Như bạn có thể thấy chúng tôi đang hiển thị thành phần phản ứng của chúng tôi thành phần tử DOM có id root
.
Cổng là gì và tại sao lại cần thiết? Tại sao nó lại ở đó?
Portals là một cách để làm cho trẻ em Phản ứng bên ngoài hệ thống phân cấp DOM chính của thành phần cha mẹ mà không làm mất phản ứng bối cảnh. Tôi đang nhấn mạnh vào nó bởi vì các thư viện rất phổ biến như react-router, redux sử dụng nhiều bối cảnh phản ứng. Vì vậy, tính khả dụng của ngữ cảnh khi sử dụng Portal
rất hữu ích.
Theo react docs,
Một trường hợp sử dụng điển hình cho các cổng thông tin là khi một thành phần cha mẹ có overflow: hidden hoặc z-index phong cách, nhưng bạn cần đứa trẻ để trực quan "bùng nổ" của container của nó. Ví dụ: hộp thoại, thẻ di chuột và chú giải công cụ.
Vì vậy, với cổng, bạn có thể hiển thị cây phản ứng song song trên nút DOM khác khi cần. Mặc dù nó được hiển thị trong nút DOM khác nhau, thành phần cha mẹ có thể nắm bắt các sự kiện chưa được nắm bắt. Xem số này codepen được cung cấp trong chính tài liệu.
Ví dụ dưới đây sẽ cung cấp cho ý tưởng hơn của bạn:
// index.html
<html>
<body>
<div id="root"></div>
<div id="another-root"></div>
</body>
</html>
// index.jsx
const mainContainer = document.getElementById('root');
const portalContainer = document.getElementById('another-root');
class HelloFromPortal extends React.Component {
render() {
return (
<h1>I am rendered through a Portal.</h1>
);
}
}
class HelloReact extends React.Component {
render() {
return (
<div>
<h1>Hello World</h1>
{ ReactDOM.createPortal(<HelloFromPortal />, portalContainer) }
</div>
);
}
}
ReactDOM.render(<HelloReact />, mainContainer);
https://codesandbox.io/s/62rvxkonnw
Bạn có thể sử dụng DevTools kiểm tra nguyên tố và thấy rằng <h1>I am rendered through a Portal.</h1>
được render bên #another-root
thẻ, trong khi <h1>Hello World</h1>
được render bên #root
thẻ.
Hope this helps :)
Cập nhật: Để trả lời câu @PhillipMunin's comment.
Sự khác nhau giữa ReactDOM.render
và ReactDOM.createPortal
là gì?
Mặc dù các thành phần được cung cấp đến các cổng được trả lại ở một nơi khác (ngoài các gốc chứa hiện hành), nó vẫn còn hiện diện như là con của cùng một thành phần cha mẹ. (Ai đã gọi số ReactDOM.createPortal
) Vì vậy, bất kỳ sự kiện nào trên trẻ được truyền cho phụ huynh. (Ofc, Tính năng này không hoạt động nếu bạn dừng phát tán sự kiện theo cách thủ công.)
Có thể truy cập bối cảnh tương tự trong thành phần được hiển thị thông qua cổng. Nhưng không phải trong trường hợp chúng tôi thực hiện trực tiếp ReactDOM.render
.
Tôi đã tạo một bản trình diễn khác để minh họa quan điểm của tôi. https://codesandbox.io/s/42x771ykwx
https://facebook.github.io/react/docs/portals.html –
Tài liệu giải thích rõ ràng cách sử dụng chúng ... bạn đã đọc chúng chưa? – ndugger
@ndugger Vâng, Tài liệu đủ tốt ngay bây giờ :). Nhưng OP đã hỏi câu hỏi 2 ngày trước. React v16 đã không được phát hành sau đó. Nó đã được phát hành ngày hôm nay và các tài liệu cũng đã có sẵn ngày hôm nay. –