es6學習1: 模擬react Comopnent類的實現
阿新 • • 發佈:2018-12-05
開始系統學習es6, 按自己的理解簡單模擬個react的Component類和生命週期思維, 見證自己的成長, 初學, 寫著娛樂, 勿噴 T.T
test.js
import mm from '../util/util.js'; class Component{ constructor(props) { this.props = {}; // 注入的history等 this.props = Object.assign(this.props, props || {}); this.state = {};this.loadComponent(); } setState(obj, fallBack){ // 判斷是否需要重新整理虛擬dom if (this.shouldComponentUpdate(obj)) { this.componentUpdate(); Object.assign(this.state,obj); this.componentDidUpdate(); this.loadComponent(); }// 呼叫回撥函式 typeof fallBack === 'function' && fallBack(); } loadComponent() { this.componentWillUMount(); this.loadProps(); this.componentDidUMount(); } loadProps(){} flushVdom(){} // 模擬生命週期函式 shouldComponentUpdate(obj){ console.log("shouldComponentUpdate"); // 物件深拷貝 let stateCopy = mm.objDeepCopy(this.state); // 合併物件 let objResult = Object.assign(stateCopy, (obj || {})); // 將setstate的值和state的值合併看和原state的值是否相等 if (mm.isEqual(objResult,this.state)) { // 相等則不重新整理元件 console.log("值相等: 不重新整理虛擬dom"); return false; } console.log("值不等, 重新整理虛擬dom"); this.flushVdom(); // 不相等重新整理元件 return true; } componentUpdate(){ console.log('componentWillUpdate'); } componentDidUpdate(){ console.log('componentDidUpdate'); } componentWillUMount(){ console.log('componentWillMount'); } componentDidUMount(){ console.log('componentDidMount'); } } class Test2 extends Component{ constructor(props){ super(props); } render(){ this.setState( {}, ()=>(console.log("setState後的回撥方法...")) ); return(`<div>我是得到的標籤</div>`) } } // 模擬呼叫 console.log(new Test2().render());
工具類 util.js (物件深拷貝及isEquels方法)
let mm = { isEqual(a, b) { //如果a和b本來就全等 if (a === b) { //判斷是否為0和-0 return a !== 0 || 1 / a === 1 / b; } //判斷是否為null和undefined if (a == null || b == null) { return a === b; } //接下來判斷a和b的資料型別 var classNameA = toString.call(a), classNameB = toString.call(b); //如果資料型別不相等,則返回false if (classNameA !== classNameB) { return false; } //如果資料型別相等,再根據不同資料型別分別判斷 switch (classNameA) { case '[object RegExp]': case '[object String]': //進行字串轉換比較 return '' + a === '' + b; case '[object Number]': //進行數字轉換比較,判斷是否為NaN if (+a !== +a) { return +b !== +b; } //判斷是否為0或-0 return +a === 0 ? 1 / +a === 1 / b : +a === +b; case '[object Date]': case '[object Boolean]': return +a === +b; } //如果是物件型別 if (classNameA == '[object Object]') { //獲取a和b的屬性長度 var propsA = Object.getOwnPropertyNames(a), propsB = Object.getOwnPropertyNames(b); if (propsA.length != propsB.length) { return false; } for (var i = 0; i < propsA.length; i++) { var propName = propsA[i]; //如果對應屬性對應值不相等,則返回false if (a[propName] !== b[propName]) { return false; } } return true; } //如果是陣列型別 if (classNameA == '[object Array]') { if (a.toString() == b.toString()) { return true; } return false; } }, // 物件深拷貝 objDeepCopy (data) { return JSON.parse(JSON.stringify(data)); } } export default mm;
測試
呼叫 setState({},()=>( console.log("setState後的回撥方法...") ) 輸出結果
呼叫 setState({name:'avenda'},()=>( console.log("setState後的回撥方法...") ) 輸出結果