写在前面
portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案
官方介绍
//portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案ReactDOM.createPortal(child, container)//第一个参数(child)是任何可渲染的React子元素(字符串或fragment)//第二个参数container是一个DOM元素
为什么需要Portals
当你想把父组件的某个子组件渲染到页面中其它盒子(非父组件子树)里的时候,就用 portal
场景
一般思路
可能很多同学会直接在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
引入createPortal 在react-dom中
import { createPortal } from 'react-dom'
在constructor定义参数container 就是this.node,利用window.document 记录doc参数 = > 定义this.node 创建div节点=>利用constructor当前的body下挂载在一个div节点上
constructor(props){super(props);const doc = window.document; //记录参数 利用window.documentthis.node = doc.createElement("div");// 定义this.node 创建一个div节点doc.body.appendChild(this.node); // 当前的body下挂载一个div节点}
利用createPortal( )方法传递两个参数
render() {return createPortal(<div className='dialog'><h3>Modal</h3></div>,this.node)}
在componetWillUnmout取消绑定,不然会造成重复渲染。
//在willUnmount中实现订阅和取消订阅componentWillUnmount() { window.document.body.removeChild(this.node) //记录参数 利用window.document}
写在后面
欢迎关注公众号“燕小书”,回复:“技术交流”进微信技术交流群,公众号会陆续发布优质文章。
