React Portals - 图1

写在前面

portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案

官方介绍

  1. //portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案
  2. ReactDOM.createPortal(child, container)
  3. //第一个参数(child)是任何可渲染的React子元素(字符串或fragment)
  4. //第二个参数container是一个DOM元素

为什么需要Portals

当你想把父组件的某个子组件渲染到页面中其它盒子(非父组件子树)里的时候,就用 portal

场景

写modal的时候

一般思路

可能很多同学会直接在JSX中把Modal画出来,像这样

  1. <div class="modal">
  2. <div> ... </div>
  3. { needModal ? <Modal /> : null }
  4. </div>

缺陷

  • modal生成的代码会与JSX中的代码冗余在一起,而modal的显示位置大多情况是在中间位置,目前modal与其他组件冗余,我们需要CSS的position属性控制modal位置,就要求从modal往上一直到body没有其他postion是relative的元素干扰
  • modal的样式会和其他组件的样式嵌套在一起,容易引起冲突

不好的思路

有的同学可能会想到,我们可以在最外层body标签出专门定义一个modal的位置,然后通过redux进行发射信号进行控制,其实效果就像下图。
image.png

方案

我们既希望在组件的JSX中选择使用modal,把modal用得像一个普通组件一样,但是又希望modal内容显示在另一个地方,就需要Portal上场了。
Portal就是建立一个“传送门”,让modal这样的组件在表示层和其他组件没有任何差异,但是渲染的东西却像经过传送门一样出现在另一个地方。

如何使用Portals

  1. 引入createPortal 在react-dom中

    1. import { createPortal } from 'react-dom'
  2. 在constructor定义参数container 就是this.node,利用window.document 记录doc参数 = > 定义this.node 创建div节点=>利用constructor当前的body下挂载在一个div节点上

    1. constructor(props){
    2. super(props);
    3. const doc = window.document; //记录参数 利用window.document
    4. this.node = doc.createElement("div");// 定义this.node 创建一个div节点
    5. doc.body.appendChild(this.node); // 当前的body下挂载一个div节点
    6. }
  3. 利用createPortal( )方法传递两个参数

    1. render() {
    2. return createPortal(
    3. <div className='dialog'>
    4. <h3>Modal</h3>
    5. </div>,
    6. this.node)
    7. }
  4. 在componetWillUnmout取消绑定,不然会造成重复渲染。

    1. //在willUnmount中实现订阅和取消订阅
    2. componentWillUnmount() { window.document.body.removeChild(this.node) //记录参数 利用window.document
    3. }

    写在后面

    欢迎关注公众号“燕小书”,回复:“技术交流”进微信技术交流群,公众号会陆续发布优质文章。