问题导向
Portals是什么?如何使用?
如果你都有了答案,可以忽略本文章,或去react学习地图寻找更多答案
react组件的渲染方式(层级)
组件默认会按照既定层级嵌套渲染,父组件,子组件
react的作用范围:只在html中ID为root的节点中渲染内容,root节点就是react的根节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id='root'></div> react的天地就这么大而已,哈哈
</body>
</html>
Portals作用
让子组件逃离父组件渲染,渲染在root之外
如何使用:引入ReactDOM,调用createPortal,渲染在body
import ReactDOM from 'react-dom'
const PortalsDemo = (props) => {
createPortal两个参数:元素,渲染的位置
return ReactDOM.createPortal(
<div className="modal">{
props.children}</div>, document.body
)
}
const App = () => {
return (
<PortalsDemo >hello propsChild</PortalsDemo>
)
}
此时的html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id='root'></div>
<div className="modal">hello propsChild</div> 节点在root之外
</body>
</html>
简单封装成组件
import {
useEffect } from 'react'
import ReactDOM from 'react-dom'
const CreatePortal = (props) => {
let body = document.querySelector('body')
let ele = document.createElement('div')
useEffect(() => {
ele.setAttribute('id','portal-root')
body.appendChild(ele)
return () => {
body.removeChild(ele)
}
})
return (
ReactDOM.createPortal(props.children, ele)
)
}
export default CreatePortal;
实现一个顶级浮层,弹窗组件
import React from 'react'
import CreatePortal from '../CreatePortal'
import {
Icon } from 'antd-mobile'
const Styles = {
modal: {
position: 'relative',
top: '0',
left: '0',
zIndex: '99'
},
body: {
backgroundColor: '#fff',
position: 'fixed',
height: '100%',
width: '100%',
top: '0',
left: '0',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
},
close: {
position: 'absolute',
top: '10px',
right: '10px',
}
}
const Modal = (props) => {
const {
show, styleBody, styleClose, onClose } = props
const handleClose = () => {
onClose && onClose()
}
//样式拓展,接收外部传递的样式
const _styleBody = {
...Styles.body,
...styleBody
}
const _styleClose = {
...Styles.close,
...styleClose
}
return (
<>
{
show && <CreatePortal style={
Styles.modal}>
<div style={
_styleBody}>
{
props.children}
<Icon
style={
_styleClose}
type="cross"
size="lg"
onClick={
() => handleClose()}
/>
</div>
</CreatePortal>
}
</>
);
}
export default Modal;
使用
import React, {
useState} from 'react'
import {
Button } from 'antd-mobile'
import Modal from './x'
function App(){
const [show, setShow] = useState(false)
const handleShow = () => {
setShow(true)
}
const handleClose = () => {
setShow(false)
}
return (
<Button type="primary" onClick={
handleShow}>展示弹窗</Button>
<Modal onClose={
handleClose} show={
show}>
modal要展示的内容
</Modal>
)
}
学习更多
react学习地图