react学习:Portals

问题导向

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学习地图

你可能感兴趣的:(react,reactjs)