react portals

212 阅读2分钟

写在前面

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

官方介绍

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

为什么需要Portals

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

场景

写modal的时候

一般思路

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

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

缺陷

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

不好的思路

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

\

方案

我们既希望在组件的JSX中选择使用modal,把modal用得像一个普通组件一样,但是又希望modal内容显示在另一个地方,就需要Portal上场了。

Portal就是建立一个“传送门”,让modal这样的组件在表示层和其他组件没有任何差异,但是渲染的东西却像经过传送门一样出现在另一个地方。

如何使用Portals

  1. 引入createPortal 在react-dom中
import { createPortal } from 'react-dom'
  1. 在constructor定义参数container 就是this.node,利用window.document 记录doc参数 = > 定义this.node 创建div节点=>利用constructor当前的body下挂载在一个div节点上
constructor(props){    
  super(props);
  const doc =  window.document;   //记录参数 利用window.document   
  this.node = doc.createElement("div");// 定义this.node 创建一个div节点
  doc.body.appendChild(this.node);  // 当前的body下挂载一个div节点      
} 
  1. 利用createPortal( )方法传递两个参数
render() {
  return createPortal(       
    <div className='dialog'>         
      <h3>Modal</h3>        
    </div>, 
    this.node)
} 
  1. 在componetWillUnmout取消绑定,不然会造成重复渲染。
//在willUnmount中实现订阅和取消订阅  
componentWillUnmount() {          		    window.document.body.removeChild(this.node)  //记录参数 利用window.document   
}

写在后面

  1. 欢迎关注公众号“燕小书”,回复:“技术交流”进微信技术交流群,公众号会陆续发布优质文章。
  2. 前端知识库: www.yuque.com/linhao-00ft…