Cửa sổ bật lên phương thức css codepen

Cổng cung cấp cách tốt nhất để kết xuất nút con thành nút DOM tồn tại bên ngoài hệ thống phân cấp DOM của thành phần gốc

ReactDOM.createPortal(child, container)

Đối số đầu tiên (child) là bất kỳ , chẳng hạn như một phần tử, chuỗi hoặc đoạn. Đối số thứ hai (container) là một phần tử DOM

Cách sử dụng

Thông thường, khi bạn trả về một phần tử từ phương thức kết xuất của một thành phần, phần tử đó sẽ được gắn vào DOM với tư cách là phần tử con của nút cha gần nhất

render() {
  // React mounts a new div and renders the children into it
  return (
    <div>      {this.props.children}
    div>  );
}

Tuy nhiên, đôi khi sẽ hữu ích khi chèn một phần tử con vào một vị trí khác trong DOM

render() {
  // React does *not* create a new div. It renders the children into `domNode`.
  // `domNode` is any valid DOM node, regardless of its location in the DOM.
  return ReactDOM.createPortal(
    this.props.children,
    domNode  );
}

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 gốc có kiểu overflow: hidden hoặc z-index, nhưng bạn cần thành phần con “phá vỡ” vùng chứa của nó một cách trực quan. Ví dụ: hộp thoại, thẻ di chuột và chú giải công cụ

Ghi chú

Khi làm việc với các cổng, hãy nhớ rằng điều đó trở nên rất quan trọng

Đối với các hộp thoại theo phương thức, hãy đảm bảo rằng mọi người đều có thể tương tác với chúng bằng cách tuân theo Thực tiễn tác giả theo phương thức WAI-ARIA

Dùng thử trên CodePen

Sự kiện bong bóng qua cổng

Mặc dù một cổng thông tin có thể ở bất kỳ đâu trong cây DOM, nhưng nó hoạt động giống như một React con bình thường theo mọi cách khác. Các tính năng như ngữ cảnh hoạt động giống hệt nhau bất kể cổng con có phải là cổng hay không, vì cổng vẫn tồn tại trong cây React bất kể vị trí trong cây DOM

Điều này bao gồm bong bóng sự kiện. Một sự kiện được kích hoạt từ bên trong một cổng thông tin sẽ lan truyền đến các phần tử tổ tiên trong cây React chứa, ngay cả khi các phần tử đó không phải là tổ tiên trong cây DOM. Giả sử cấu trúc HTML sau

<html>
  <body>
    <div id="app-root">div>
    <div id="modal-root">div>
  body>
html>

Một thành phần

render() {
  // React mounts a new div and renders the children into it
  return (
    <div>      {this.props.children}
    div>  );
}
0 trong
render() {
  // React mounts a new div and renders the children into it
  return (
    <div>      {this.props.children}
    div>  );
}
1 sẽ có thể bắt một sự kiện sủi bọt, chưa được bắt từ nút anh chị em
render() {
  // React mounts a new div and renders the children into it
  return (
    <div>      {this.props.children}
    div>  );
}
2

// These two containers are siblings in the DOM
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // The portal element is inserted in the DOM tree after
    // the Modal's children are mounted, meaning that children
    // will be mounted on a detached DOM node. If a child
    // component requires to be attached to the DOM tree
    // immediately when mounted, for example to measure a
    // DOM node, or uses 'autoFocus' in a descendant, add
    // state to Modal and only render the children when Modal
    // is inserted in the DOM tree.
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(      this.props.children,      this.el    );  }
}

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {clicks: 0};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {    // This will fire when the button in Child is clicked,    // updating Parent's state, even though button    // is not direct descendant in the DOM.    this.setState(state => ({      clicks: state.clicks + 1    }));  }
  render() {
    return (
      <div onClick={this.handleClick}>        <p>Number of clicks: {this.state.clicks}p>
        <p>
          Open up the browser DevTools
          to observe that the button
          is not a child of the div
          with the onClick handler.
        p>
        <Modal>          <Child />        Modal>      div>
    );
  }
}

function Child() {
  // The click event on this button will bubble up to parent,  // because there is no 'onClick' attribute defined  return (
    <div className="modal">
      <button>Clickbutton>    div>
  );
}

const root = ReactDOM.createRoot(appRoot);
root.render(<Parent />);

Dùng thử trên CodePen

Nắm bắt một sự kiện nổi lên từ một cổng thông tin trong thành phần chính cho phép phát triển các bản tóm tắt linh hoạt hơn vốn không phụ thuộc vào cổng thông tin. Ví dụ: nếu bạn kết xuất một thành phần

render() {
  // React mounts a new div and renders the children into it
  return (
    <div>      {this.props.children}
    div>  );
}
3, thành phần gốc có thể nắm bắt các sự kiện của thành phần đó bất kể thành phần đó có được triển khai bằng cổng hay không