react portals

Posted bruce-gou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react portals相关的知识,希望对你有一定的参考价值。

来源:https://segmentfault.com/a/1190000011668286

Portals是react 16.3 提供的官方解决方案,使得组件可以脱离父组件层级挂载在DOM树的任何位置。

 

普通情况下,组件的render函数返回的元素会被挂载在它的父级组件上。

import DemoComponent from ./DemoComponent;
render() {
  // DemoComponent元素会被挂载在id为parent的div的元素上
  return (
    <div id="parent">
        <DemoComponent />
    </div>
  );
}

 

然而,有些元素需要被挂载在更高层级的位置。最典型的应用场景:当父组件具有overflow: hidden或者z-index的样式设置时,组件有可能被其他元素遮挡,这个时候你就可以考虑要不要使用Portal使组件的挂载脱离父组件。例如:对话框,tooltip。

import DemoComponent from ./DemoComponent;

render() {
  // react会将DemoComponent组件直接挂载在真真实实的 dom 节点 domNode 上,生命周期还和16版本之前相同。
  return ReactDOM.createPortal(
    <DemoComponent />,
    domNode,
  );
}

 

组件的挂载点虽然可以脱离父组件,但组件的事件通过冒泡机制仍可以传给父组件。

 

官方domo

// 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() {
    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(prevState => ({
      clicks: prevState.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>Click</button>
    </div>
  );
}

ReactDOM.render(<Parent />, appRoot);

 

 

 

以上是关于react portals的主要内容,如果未能解决你的问题,请参考以下文章

[译文]React v16(新特性)

React Portal 案例学习

[react] 你有用过React的插槽(Portals)吗?怎么用?

react portals

[react] 请说说react中Portal是什么?

javascript 旧版React Portal