目录
最近在看React的官方文档,补习一下有关React的知识,这篇文章就介绍一下如何使用ReactDOM.createPortal来实现弹框组件的改造;比较初级,比较通俗易懂。
Portal ,将子节点渲染到存在于父组件以外的 DOM 节点。
ReactDOM.createPortal(child, container)
第一个参数(
child
)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container
)是一个 DOM 元素。
上面的这句话引用自React的官方API,很通俗易懂,接下来看一下具体实现的例子
一.创建container元素
把这个container元素用A组件表示,创建A.jsx文件,如下代码:
const A = (props: any) => {
return (
<>
<div id="modal-root" />
<div id="father" />
</>
)
}
export { A }
二.创建C元素
这个C元素用来承载Modal元素,代码如下:
const C = () => {
const [ show, setShow ] = useState(false)
const onClose = () => {
console.log("C onClose")
setShow(false)
}
return (
<div>
C,
<Modal show={show} onClose={onClose} />
<button onClick={() => setShow((i) => !i)}>change展开/折叠Modal</button>
</div>
)
}
export { C }
三.创建Modal元素
import React, { Children, useEffect, useState } from "react"
import ReactDOM from "react-dom"
import "./c1.less"
const Modal = (props: any) => { // 第一次渲染dom 走生命周期 还会在渲染拿值
// console.log(props, 1114)
const [ target, setTarget ] = useState(null)
// console.log(target, 1111, target)
useEffect(() => {
// console.log(1, document.getElementById("modal-root"))
setTarget(document.getElementById("modal-root") as any)
}, [])
useEffect(() => {
// console.log("show change", props.show)
}, [ props.show ])
if (!props.show) return null // false 就返回null
const close = () => {
console.log("modal close")
props.onClose()
}
const children = (
<div className="modal">
modal <button onClick={close}>close</button>
</div>
)
// console.log("Modal", children, target)
// target 一拿到dom 就会添加一个dom 到 target
return target ? ReactDOM.createPortal(children, target as any) : <div>无父元素</div>
}
c1.less对应的代码:
.modal {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
text-align: center;
z-index: 9999;
background: rgba(0,0,0, .3);
}
四.展现元素
import { A } from './A'
import { C } from './C'
export default class Miao extends Component<Props, State> {
render(){
return (
<>
<A/>
<C/>
</>
)
}
}
五.页面展现效果
![](https://i-blog.csdnimg.cn/blog_migrate/5d7c33286e485a3c2e8e04f1e5d32529.png)
再来看一下dom结构树
可以看到modal就是在modal-root的子级,就是添加到了子级,是不是很强大的一个API呢,喜欢的话,就在项目中用起来吧!