lgwebdream / FE-Interview

🔥🔥🔥 前端面试,独有前端面试题详解,前端面试刷题必备,1000+前端面试真题,Html、Css、JavaScript、Vue、React、Node、TypeScript、Webpack、算法、网络与安全、浏览器
https://lgwebdream.github.io/FE-Interview/
Other
6.76k stars 897 forks source link

Day363:举例说明 React 的插槽有哪些运用场景?你有用过 React 的插槽(Portals)吗?怎么用? #1196

Open Genzhen opened 2 years ago

Genzhen commented 2 years ago

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解

二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。


Portals

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

应用场景

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

具体使用

ReactDOM.createPortal(child, container);
render() {
  // React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
  // `domNode` 是一个可以在任何位置的有效 DOM 节点。
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

具体应用示例

实现一个全局浮层:

<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;
}
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);