美文网首页
React 使用Portals手写模态框Dialog

React 使用Portals手写模态框Dialog

作者: 弦生_a3a3 | 来源:发表于2022-05-12 22:55 被阅读0次

    如何引用Protals

    Portabls是ReactDom中的方法,通过ReactDom.createPortal(child,dom)使用的
    child:任何可渲染的 React元素
    dom:当前绑定于哪个DOM元素中

    Portabls作用

    某些情况下,我们想将某些内容独立于父组件,甚至于当前挂在DOM元素中root等。


    使用手写dialog模态框示例:

    index.html页面

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="theme-color" content="#000000" />
        <meta
          name="description"
          content="Web site created using create-react-app"
        />
        <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
      
        <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    
        <title>React App</title>
      </head>
      <body>
        <noscript>You need to enable JavaScript to run this app.</noscript>
        <div id="root"></div>
        <div id="model"></div>
    
      </body>
    </html>
    
    

    在index.html中加入DOM元素,id取名为model,后期做Portals DOM绑定


    model.js 组件,弹窗组件

    import  { PureComponent } from 'react';
    import { createPortal } from 'react-dom';
    import propTypes from 'prop-types';
    import './index.css';
    export default class Model extends PureComponent {
        static propTypes={
            title:propTypes.string,
            width:propTypes.string,
            top:propTypes.string,
            show:propTypes.bool.isRequired,
            closeModel:propTypes.func
        }
        static defaultProps={
            title:'标题',
            width:'30%',
            top:'15vh',
            show:false
        }
        constructor(props){
            super(props)
        }
        render() {
            const { children,title,width,top,show , closeModel }=this.props;
            const modelChild=(
            <div className={ ` ${show?'active':''} model-container` }>
                <div className={ ` ${show?'active':''} h-model` }
                  style={ {top,width,left:`calc(50% - ${parseFloat(width)/2}%)`} }>
                    <div className="model-header">
                        <h2>{ title }</h2>
                        <i onClick={ closeModel }>x</i>
                    </div>
                    <div className="model-aside">{children}</div>
    
                    <div className="model-footer">
                            <button className="btn del">取消</button>
                            <button className="btn sure">确定</button>
                    </div>
                </div>
            </div>
            )
            return createPortal(
                modelChild,
                document.getElementById('model')
            )
        }
    }
    
    

    将props.child抽离出来,放在modelChild重新进行渲染,通过ES6结构语法,将createPortal方法拿出来进行使用。
    createPortal第一个参数:modelChild表示,绑定需要渲染的组件。
    createPortal第二个参数:表示,将组件放入改DOM内部。


    DemoBlock.js 组件,内部事件点击渲染Dialog组件

    import React, { PureComponent } from 'react'
    import './index.css'
    import Model from '../Model/index';
    export default class DemoBlock extends PureComponent {
        constructor(props){
            super(props)
            this.state={
                show:false
            }
        }
        render() {
            const { show } = this.state;
            return (
                <div className="demo-block">
                     <Model closeModel={ this.closeModel.bind(this) }  show={ show }>
                        {
                            <p>这是一段段落描述</p>
                        }
                    </Model>
    
                    <h3>这里是测试模块</h3>
                    <button onClick={ ()=>this.open(show) }>弹窗测试</button>
                </div>
            )
        }
        closeModel(){
            console.log('执行了关闭')
            this.setState({
                show:false
            })
        }
        open(type){
            console.log('开始执行')
            this.setState({
                show:!type
            })
        }
    }
    
    

    Model组件内部标签,在Model中都可以通过props.children获取到


    渲染后成果,当然样式还是要自己写,主要梳理功能

    chrome-capture-2022-4-12.gif

    相关文章

      网友评论

          本文标题:React 使用Portals手写模态框Dialog

          本文链接:https://www.haomeiwen.com/subject/wkneurtx.html