react 反模式——不使用jsx動態顯示異步組件 React反模式 —— 如何不使用JSX地動態顯示組件

前言:html

  react反模式 (anti-patterns)指的是違背react思想(flux)的coding方式。react

  本文在 App 組件中,經過 Model.show 動態顯示 Model 組件,經過 Promise 異步的形式實現數據交互。git

  本例子包括了 1.不使用jsx動態顯示組件;2.在 getInitialState 中使用 this.props github

  代碼地址:https://github.com/miaowwwww/react-anti-patternspromise

    參考文章:app

    React反模式 —— 如何不使用JSX地動態顯示組件less

    怎麼樣理解reactjs中組件的反模式? dom

    react-patterns異步

先看一下效果:函數

  

  調用代碼:

    

 

 實現1:如何不經過父組件jsx嵌套,動態顯示 Model 組件?

  (拋開父組件,也就是怎麼把一個react組件渲染到DOM中去而已)

  過程:新容器(div) ---> Model注入div ---> div注入body;

  代碼:(就是紅框部分:無論何時執行  show()  這三行代碼,均可以放一個Model組件到body裏面)

    

  

 實現2:如何實現使用者與Model組件的數據交互?

  (要把點了什麼以及新名字告訴調用 Model.show() 的人)

  要點:異步傳遞數據Promise, Model.show()  是Model裏面的static方法--是類自己的

  過程:App 調用 Model.show ---> Model.show 返回一個Promise ---> App在Promise中獲取數據

  代碼:

    1.App調用Model.show(),並接受、處理promise

    

    2.Model如何返回一個Promise

      2.1 在Model中聲明Promise(注意:Model如今是沒有this._promise的,<Model />實例化以後,實例裏面有_promise)

      2.2 在show函數中,

        2.2.1:使用ReactDOM.render(<Model />, div),實例化一個Model組件,並把該實例返回。所以_model 有一個_promise

    

 

實現3:Promise的resolve & reject 返回交互數據

  使用組件內使用定義好的 this._resolve, this._reject就行了

  

 

實現4: 銷燬Model組件和產生的div容器

   4.1 ReactDOM.unmountComponentAtNode(container);

     用於銷燬react組件,container:ReactDOM.render(<Model />, div),這裏的div就是;因此知道show的時候爲何要留着引用了吧

  4.2 div容器仍是留着的,因此必需要用基本js銷燬;(先remove 再 unmount行不行?好像更好,減小一次dom操做)

  

 

Model的完整代碼

 

import React, { PureComponent, PropTypes } from 'react';
import ReactDOM from 'react-dom';

import style from './Model.less';

export default class Model extends PureComponent {
    constructor(props) {
        super(props);
        // 使用this.props初始化this.state也是反模式的一種
        this.state = {name: this.props.name};

        this._reject = null;
        this._resolve = null;
        this._promise = new Promise((resolve, reject) => {
            this._resolve = resolve;
            this._reject = reject;
        });
        this._container = null;
    }

    static show = (name) => {
        // 顯示組件
        let div = document.createElement('div');
            // _model 就是當前的 Model的一個實例
        let _model = ReactDOM.render(<Model name={name} />, div);
        document.querySelector('body').appendChild(div);
        
        _model._container = div; //在_model實例中保存div的引用,銷燬要用
        // 返回一個promise
        return _model._promise;
    }

    // 銷燬 1.銷燬react組件 2.銷燬 div 元素
    _removeModel = () => {
        this._container.remove();
        ReactDOM.unmountComponentAtNode(this._container);
    }

    handleChange = (e) => {
        this.setState({name: e.target.value});
    }

    handleClickSave = () => {
        this._resolve(this.state.name);
        this._removeModel();
    }

    handleClickCancel = () => {
        this._reject(`cancen update name`);
        this._removeModel();
    }

    render() {
        return (
            <section className={style.model}>
                <div className={style.content}>
                    <h1>請輸入新名字</h1>
                    <input type="text" 
                                value={this.state.name} 
                                onChange={this.handleChange} />
                    <div>
                        <a onClick={this.handleClickCancel} >取消</a>
                        <a onClick={this.handleClickSave} >保存</a>
                    </div>
                </div>
            </section>
        )
    }
}
Model.PropTypes = {
    name: PropTypes.string.isRequired
}
相關文章
相關標籤/搜索