• React对话框组件实现


    当下前端届最火的技术之一莫过于React + Redux + webpack的技术结合。最近公司内部也正在转react,这周主要做了个React的modal组件,接下来谈下具体实现过程。

    基本的HTML结构

    虽然React基于虚拟DOM,但他的JSX语法还是离不开最基本的HTML。第一步要做的就是通过HTML&&CSS实现Dialog垂直水平居中框。HTML结构如下:

                    <div className="m-mask"></div>
                    <div className="m-dialog">
                        <div className="md-dialog">
                            <div className="md-dialog-title">
                                <h4>{title}</h4>
                                <span className="btn">
                                    <i className="iconfont">&times;</i>
                                </span>
                            </div>
                            <div className="md-dialog-content">
                                {this.props.children}
                            </div>
                            <div className="md-dialog-foot">
                                <a href="#" className="btns">取消</a>
                                <a href="#" className="btns btns-blue">确定</a>
                            </div>
                        </div>
                    </div>
    

    ps: JSX语法的className对应于HTML中的class,其次文中的iconfont图标被换成了&times;
    然后写下对应的CSS样式。此处主要说明一下主要的样式布局原理,细节略过。
    Modal框的背景mask样式通过position:fixed + top/right/bottom/left:0 + height: 100%实现。
    不定宽高的主体内容水平垂直居中的实现通过position:fixed + top/left: 50% + translate(-50%, -50%)实现。

    React Modal Component

    有了已经想好的布局样式,开始实现最基本的Modal组件。因为需要动态控制组件的显隐,所以组件的显隐在内部要通过state方便控制,而其他属性则通过props实现。modal.js代码如下:

    import React, { Component, PropTypes } from 'react'
    
    const defaultProps = {
        show: false,
        title: '',
        zIndex: 1000,
        onOk: () => {},
        onCancel: () => {},
    }
    
    const propTypes = {
        title: PropTypes.string,
        zIndex: PropTypes.number,
        onOk: PropTypes.func,
        onCancel: PropTypes.func,
    }
    
    export default class Modal extends Component {
        constructor(props) {
            super(props)
            this.state = {show: props.show}
        }
        render() {
            return (
                    // JSX语法的HTML
                       );
        }
    }
    
    Modal.defaultProps = defaultProps
    Modal.propTypes = propTypes
    

    不过显隐内部通过state控制,但父组件还是需要通过props传递初始默认值。而且来回调用同一个modal时,父组件是通过props中的show属性控制。内部的state还是第一次调用时传入的props值。这样无法导致及时控制显隐。此时react的componentWillReceiveProps()出场,完美解决这个bug。
    俗话说bug是解不完的,虽然上面的组件勉强可以正常使用,但是用于样式通过绝对定位来做的,无形中导致了另外一个坑,如果Modal的父组件采用了相对或者绝对定位,即影响了Modal组件的定位,就会存在Modal出现在了某个div中,而不是理想的body中。bug复现如下:

    unstable_renderSubtreeIntoContainer登场

    为了保证我们的组件始终处于body中,采取了ReactDOM中的的这个不太正式的API。语法很简单:

    ReactDOM.unstable_renderSubtreeIntoContainer(parent, component, dom)
    

    parent一般是this,component是Modal,dom是div
    代码实现如下:

    export default class extends Component {
        appendMaskIntoDoc() {
            ReactDOM.unstable_renderSubtreeIntoContainer(
                this,
                <Modal {...this.props}>
                    {this.props.children}
                </Modal>,
                this.container
            )
        }
    
        componentDidMount() {
            this.container = document.createElement('div')
            document.body.appendChild(this.container)
            this.appendMaskIntoDoc()
        }
    
        componentDidUpdate() {
            this.appendMaskIntoDoc()
        }
    
        componentWillUnmount() {
            document.body.removeChild(this.container)
        }
    
        render() {
            return null
        }
    }
    
    API形式

    此时,Modal组件已经成功做出来了。父组件可以成功调用,效果如下:

    不过,偷偷see了下蚂蚁金服官网的Modal组件调用,还有一种API形式的调用。于是也简单实现了下。这里,简单说下实现思路吧。
    Confirm function内部通过setState方法函数接受的参数传递给Modal的父组件dialog,onOk的promise异步回调则是在dialog内部通过处理之后再传递给Modal组件。
    此处我是通过正则表达式检测new Promise,如果属于Promise,则给onOk绑定then,内部调用setState控制Modal的隐藏。不过在调用Confirm function之前,
    dialog组件已经被render进ReactDOM中,render之前则需要dom节点,就需要能获取到document节点。然后手动创建空div节点添加到body中。
    此处代码有点长,省略咯。

    完整的代码已放到github上。https://github.com/qingguoing/react-modal
  • 相关阅读:
    Java 8 Stream流编程学习
    AMD R5 2400G插帧教程
    GCC编译Win图形程序不显示控制台方法
    Linux程序守护脚本
    远程桌面软件RDCMan汉化版
    Java基础知识点
    Java的String类常用方法
    Apache Commons 相关工具类使用
    基于OpenCV的双目视觉匹配测距系统
    异想家Ubuntu安装的软件
  • 原文地址:https://www.cnblogs.com/qingguo/p/5701302.html
Copyright © 2020-2023  润新知