react學習之彈出層

react的彈出層不一樣於以往的DOM編程,咱們知道,在DOM中,彈出層事件綁定在對應的節點上便可,可是在react中,每每只能實現父子之間的傳遞控制,顯然,彈出層的層級不符合此關係。
在這裏咱們須要使用React官方的portalscss

portals能夠幫助咱們將子節點插入到父節點層級以外的地方
注:官方文檔使用的是class,我在這裏使用的是react hook
在reacthtml

前置知識

react hook
useEffect是了react生命週期中的componentDidMountcomponentDidUpdate以及componentWillUnMount三個鉤子函數的組合。react

  • 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插入DOMapp

(1)首先獲取咱們要插入的DOM節點id=model-rootdom

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

(2)建立一個存放子節點的元素el函數

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

(3)在componentDidMount階段將el節點插入model-rootui

//初始化工做
    useEffect(()=>{

        modelRoot.appendChild(el);

    },[])

(4)渲染組件,執行createPortal方法excel

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;

最終的醜陋效果

相關文章
相關標籤/搜索