• react学习之弹出层


    react的弹出层不同于以往的DOM编程,我们知道,在DOM中,弹出层事件绑定在对应的节点上即可,但是在react中,往往只能实现父子之间的传递控制,显然,弹出层的层级不符合此关系。
    在这里我们需要使用React官方的portals

    portals可以帮助我们将子节点插入到父节点层级之外的地方
    注:官方文档使用的是class,我在这里使用的是react hook
    在react

    前置知识

    react hook
    useEffect是了react生命周期中的componentDidMountcomponentDidUpdate以及componentWillUnMount三个钩子函数的组合。

    • useEffect有两个参数
    • useEffect第二个参数为空数组相当于在componentDidMount周期执行一次
    • useEffect第二个参数为含有某种state的数组相当于只有在这个state发生改变的时候才执行
    • useEffect返回一个函数相当于在componentWillUnMount周期执行一次

    实现步骤

    1.首先,选择要插入弹出层的DOM节点,在这里我参照官方文档将整个项目分成了app-rootmodel-root两层,我将把弹出层插入到model-root节点中

    function App(){
        return(
            <React.Fragment>
                <div id={"app-root"}>
                    <Router/>
    
                </div>
                
                <div id={"model-root"}></div>
            </React.Fragment>
        )
    }
    export default App;

    2.实现弹出层
    我们按照官方文档,先生成一个节点el作为存放我们子节点的容器,并执行ReactDOM.createPortal

    ReactDOM.createPortal(child, container)

    我们需要先将我们的el节点插入选定的DOM节点,然后再将portal元素插入DOM树中,故我们先用hook在componentDidMount阶段将el插入DOM

    (1)首先获取我们要插入的DOM节点id=model-root

     const modelRoot = document.getElementById('model-root');

    (2)创建一个存放子节点的元素el

    const [el,changEl] = useState(document.createElement('div'));

    (3)在componentDidMount阶段将el节点插入model-root

        //初始化工作
        useEffect(()=>{
    
            modelRoot.appendChild(el);
    
        },[])

    (4)渲染组件,执行createPortal方法

        return ReactDOM.createPortal((
            <Content closeModel={props.closeModel}/>
        ), el);

    (5)在componentWillUnMount阶段移除我们的el节点

        //清理工作
        useEffect(()=>{
            return ()=>{
                modelRoot.innerHTML="";
    
            }
        })

    完整代码如下:

    import React,{useState,useEffect} from 'react';
    import './Model.css';
    import ReactDOM from "react-dom";
    import ExcelUtil from '../../utils/excelUtil';
    
    
    function Content(props) {
        return(
            <div className={'cover'}>
                <button onClick={props.closeModel}>关闭</button>
                <input type='file' accept='.xlsx, .xls' onChange={(e)=>{ExcelUtil.importExcel(e)} }/>
    
            </div>
        )
    }
    
    function Model(props){
        const appRoot = document.getElementById('app-root');
        const modelRoot = document.getElementById('model-root');
        const [el,changEl] = useState(document.createElement('div'));
    
        //初始化工作
        useEffect(()=>{
    
            modelRoot.appendChild(el);
    
        },[])
        //清理工作
        useEffect(()=>{
            return ()=>{
                modelRoot.innerHTML="";
    
            }
        })
        return ReactDOM.createPortal((
            <Content closeModel={props.closeModel}/>
        ), el);
    }
    
    export default Model;

    这样子子元素就出现在了我们想要的DOM层级中

    3.在调用页中引入我们的Model并定义相关触发事件,这些与子节点向父节点的方式传值无异

      {(isShowPop == true)?<Model isShow={isShowPop} closeModel={handleInClick}/>:null}
    
    function RegisterInUser() {
        const [isShowPop,changeShowPop] = useState(false);
        function handleInClick(){
            changeShowPop(!isShowPop);
        }
        return(
            <React.Fragment>
    //这里是使用的地方
                {(isShowPop == true)?<Model isShow={isShowPop} closeModel={handleInClick}/>:null}
    
    
                <button className="ui-button ui-button-primary"  onClick={handleInClick}>导入人员</button>
                <button
                    className="ui-button ui-button-primary outExcelBtn"
                    type="primary"
                    onClick={() => {ExcelUtil.exportExcel(initColumn, attendanceInfoList,"人员名单.xlsx")}}>
                    导出表格
                </button>
    
    
            </React.Fragment>
        )
    }
    
    export default RegisterInUser;
    

    最终的丑陋效果

    1394463-20190605172503737-1873170032.png

    1394463-20190605172532782-1383307045.png

    转载于:https://www.cnblogs.com/yuyuan-bb/p/10980834.html

  • 相关阅读:
    探索SaaS产业发展新机遇|鲁班会贵安首秀圆满收官
    带你认识三种kafka消息发送模式
    常用的echo和cat,这次让我折在了特殊字符丢失问题上
    当MySQL执行XA事务时遭遇崩溃,且看华为云如何保障数据一致性
    一图解析MySQL执行查询全流程
    HDFS源码解析:教你用HDFS客户端写数据
    大型集团企业云管平台建设参考架构
    带你了解家居智能的心脏:物联网关
    带你认识7种云化测试武器
    实践解析可视化开发平台FlinkSever优势
  • 原文地址:https://www.cnblogs.com/twodog/p/12134836.html
Copyright © 2020-2023  润新知