2022-09-26React00
请注意,本文编写于 568 天前,最后修改于 568 天前,其中某些信息可能已经过时。

Portals

插槽(Portals)能将子节点渲染到父组件的 DOM 层次之外。

应用场景

当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框。

具体使用

ReactDOM.createPortal(child, container);
  • 第一个参数 child 是任何可渲染的 React 子元素,例如一个元素,字符串或片段(fragment)。
  • 第二个参数 container 则是一个 DOM 元素
render() {
  // React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
  // `domNode` 是一个可以在任何位置的有效 DOM 节点。
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

具体应用示例

实现一个全局浮层:

  • html
<body>
  <div id="app-root"></div>
  <div id="mask-root"></div>
</body>

-css

#modal-root {
  position: relative;
  z-index: 999;
}
.modal {
  color: #fff;
  background-color: rgba(0, 0, 0, 1);
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
  • react
const appRoot = document.getElementById('app-root');
const maskRoot = document.getElementById('mask-root');
class Mask extends React.Component{
  constructor(props){
    super(props);
    this.el = document.createElement('div');
  }
  componentDidMount()){
    maskRoot.appendChild(this.el);
  }
  componentWillUnmount(){
    maskRoot.removeChild(this.el);
  }
  render(){
    return ReactDom.createPortal(
      this.props.children,
      this.el
    )
  }
}
class App extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      showMask:false
    }
    this.handler = this.handler.bind(this);
  }
  handler(){
    let showMask = this.state.showMask;
    this.setState({showMask:true})
  }
  render(){
    let showMask = this.state.showMask;
    let mask = showMask ?
      <Mask>
        <div className="modal">
            测试
            <button onClick={this.handler}>hidden</button>
        </div>
      </Mask>
      :null;
    return (
      <div>
        this div has overflow:hidden.
        <button onClick={this.handler}>show</button>
        {mask}
      </div>
    )
  }
}
ReactDOM.render(<App />,appRoot);

本文作者:前端小毛

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!