react有关的一些事-如何创建一个基于react的modal组件

看了一下,上一篇文章还是1.1号写的,一恍二十多天过去了。随便写一点react有关的东西吧,这一篇文章主要参考了https://www.cnblogs.com/demod...
第一步:先写静态模版

src/component/Modal.tsx
import React from 'react';
import PropTypes from 'prop-types';
import './Modal.css'
interface ModalProps {
    onOk: (event: React.MouseEvent) => void;
    onCancel: (event: React.MouseEvent) => void;
    title: string;
    children: PropTypes.ReactElementLike;
}

export default class Modal extends React.Component {
    render() {
        return (
            
{this.props.title}
{this.props.children}
) } }

样式随便写写:

.modal-container {
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background-color:rgba(4,4,4, 0.45);
}

.modal-instance {
    position: absolute;
    top: 50%;
    left: 50%;
    background-color: #ffffff;
    transform: translate(-50%, -50%);
    border-radius: 3px;
    border-style: 1px solid #353535;
}
.modal-title {
    height: 20px;
    width: 100%;
    min-width: 500px;
    font-size: 16px;
    font-weight: 500;
    display: flex;
    align-items: center;
}
.modal-content {
    padding: 5px;
}
.modal-footer {
    height: 30px;
    font-size: 14px;
    display: flex;
    align-items: center;
}

现在开始调用modal:

class Game extends React.Component {

  constructor(props: Props) {
    super(props);
    this.state = {
      isShowModal: false
    }
  }

  openModal = () => {
    this.setState({
      isShowModal: true
    })
  }
  render() {
    const ModalProps = {
      onOk: (event: React.MouseEvent) => {},
      onCancel:(event: React.MouseEvent) => {},
      title: '测试modal',
    }
    const { isShowModal } = this.state;
     return (<>
             {isShowModal && 
          
{'modal content'}
} );

现在为止我们完成了一个简单的静态的modal弹框。现在我们希望提供更多的调用方式,比如我希望使用ModalService.open(template, {onOk: () => {}, onCancel: () => {}})这种api进行调用。那我们就需要进行封装:

export class ModalService {
    static open(props: ModalProps) {
        const modalContainer = document.createElement('div');
        document.body.appendChild(modalContainer);
        function onOk() {
            props.onOk();
            ReactDOM.unmountComponentAtNode(modalContainer);
        }

        function onCancel() {
            props.onCancel();
            ReactDOM.unmountComponentAtNode(modalContainer);
        }
        ReactDOM.render(, modalContainer);
    }
}

现在我们来测试一下ModalService.open的调用弹框方式

  openModalService = () => {
    const inputNameChange = (event: React.ChangeEvent) => {
      this.setState({
        inputName: event.target.value
      });
    }
    ModalService.open({
      onOk: () => {
        console.log(this.state.inputName);
        console.log('modal submit  by service, and close')
      },
      onCancel: () => {
        this.setState({
          inputName: ''
        })
        console.log('modal cancel ❌ by service, and close')
      },
      title: '这是service打开的',
      children: ()
    })
  }

这里其实有个bug,这里的input弹框绑定了value={this.state.inputName} 来绑定,但是其实这个element并没有真正的完成数据绑定,因为他只是创建了一次,并没有和render函数关联所以会出现,任何对input文本框的输入,都看不到的情况。所以在有输入模版为form的情况下,更好的方式是使用组件调用,在render中使用组件调用的方式。

        {isShowModal && 
          
{'modal content'}
}

类似这样写。或者modalservice.open的方式打开一个render方法中定义的ref。但是这样好像不太符合react哲学(so?
最后封装一个链式调用的api吧。
1.先改造modalservice使他返回一个promise

export class ModalService {
    static open(props: ModalProps) {
        const modalContainer = document.createElement('div');
        document.body.appendChild(modalContainer);
                return new Promise((resolve, reject) => {
            function onOk() {
                props.onOk && props.onOk();
                ReactDOM.unmountComponentAtNode(modalContainer);
                resolve();
            }

            function onCancel() {
                props.onCancel && props.onCancel();
                ReactDOM.unmountComponentAtNode(modalContainer);
                reject();
            }
            ReactDOM.render(, modalContainer);
        })

    }
}

调用方式改为:

    openModalServicePromise = async () => {
        ModalService.open({
            title: '期待返回promise进行链式调用',
            children: '这是期待的promise返回的格式,这样更好用感觉'
        }).then(() => {
            console.log('modal 点击了确定✅, and close')
        }).catch(() => {
            console.log('modal 点击了取消️, and close')
        })
    }

简直perfect!

你可能感兴趣的:(react有关的一些事-如何创建一个基于react的modal组件)