前言:
react反模式 (anti-patterns)指的是違背react思想(flux)的coding方式。
本文在 App 組件中,通過 Model.show 動態顯示 Model 組件,通過 Promise 異步的形式實現數據交互。
本例子包括了 1.不使用jsx動態顯示組件;2.在 getInitialState 中使用 this.props
代碼地址:https://github.com/miaowwwww/react-anti-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 }
文章列表
留言列表