React的主要思想是經過構建可複用組件來構建頁面.
所謂組件,其實就是有限狀態機(FSM),經過狀態渲染對應的界面,且每一個組件都有本身的生命週期,
它規定了組件的狀態和方法須要在哪一個階段改變和執行.react
class Collections extends Component { constructor(props) { super(props); this.state = { a: 1 } } add = () => { this.setState({ a: this.state.a + 1 }); } componentWillMount() { console.log('componentWillMount'); } componentDidMount() { console.log('componentDidMount'); this.setState({ a: 2 }); } componentWillUnMount() { console.log('componentWillUnMount'); } render() { console.log('render'); return ( <div className="collections"> { this.state.a } <Example a={ this.state.a } /> <button onClick={ this.add }>btn</button> </div> ); } }
import React, { Component, PropTypes } from 'react'; export default class Example extends Component { static propTypes = { a: PropTypes.number.isRequired }; static defaultProps = { a: 0 }; constructor(props) { super(props); this.state = { b: 1 }; } add = () => { this.setState({ b: this.state.b + 1 }); } componentWillReceiveProps(nextProps) { console.log(nextProps); if (nextProps.a === 4) { this.setState({ b: 1000 }); } } shouldComponentUpdate(nextProps, nextState) { console.log(nextProps); console.log(nextState); if (nextState.b === 4) { return false; } return true; } componentWillMount() { console.log('子組件componentWillMount'); } componentDidMount() { console.log('子組件componentDidMount'); } render() { console.log('子組件render'); return ( <div> <p>a:{ this.props.a }</p> <p>b:{ this.state.b }</p> <button onClick={ this.add }>子組件add</button> </div> ); } }
當首次掛載組件時,按順序執行getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
當卸載組件時,執行componentWillUnMount
當再次渲染組件時,組件接收到更新狀態,此時按順序執行componentWillReceiveProps,shouldComponentUpdate,
componentWillUpdate,render和componentDidUpdate異步
createClass是建立自定義組件的入口方法,負責管理生命週期方法中的getDefaultProps.
該方法在整個生命週期中只執行一次,這樣全部實例初始化的props將會被共享.
經過createClass建立自定義組件,利用原型繼承ReactClassComponent父類,
按順序合併minin,設置初始化defaultProps,返回構造函數.
當使用ES6 classes編寫React組件時,class MyComponent extends React.Component
其實就是調用內部方法createClass建立組件.函數
var ReactClass = { // 建立自定義組件 createClass: function(spec) { var Constructor = function(props, context, updater) { // /自動綁定 if (this._reactAutoBindPairs.length) { bindAutoBindMethods(this); } this.props = props; this.context = context; this.refs = emptyObject; this.updater = updater || ReactNoopUpdateQueue; this.state = null; // ReactClass沒有構造函數,經過getInitialState和componentWillMount來代替 var initialState = this.getInitialState ? this.getInitialState() : null; this.state = initialState; }; // 原型繼承父類 Constructor.prototype = new ReactClassComponent(); Constructor.prototype.constructor = constructor; Constructor.prototype._reactAutoBindPairs = []; // 合併mixin injectedMixins.forEach( minSpecIntoComponent.bind(null, Constructor) ); minSpecIntoComponent(Constructor, spec); // 全部mixin合併後初始化defaultProps(在整個生命週期中,getDefaultProps只執行一次) if (Constructor.getDefaultProps) { Constructor.defaultProps = Constructor.getDefaultProps(); } // 減小查找並設置原型的時間 for (var methodName in ReactClassInterface) { if (!Constructor.prototype[methodName]) { Constructor.prototype[methodName] = null; } } return Constructor; } };
mountComponent負責管理生命週期中的getInitialState,componentWillMount,render和componentDidMount
因爲getDefaultProps是經過構造函數進行管理的,因此也是整個生命週期中最早開始執行的.
react是利用更新隊列this._pendingStateQueue以及更新狀態this._pendingReplaceState
和this._pendingForceUpdate來實現setState的異步更新機制.
其實,mountComponent本質上是經過遞歸渲染內容的,因爲遞歸的特性,父組件的componentWillMount
在其子組件的componentWillMount以前調用,而父組件的componentDidMount在其子組件的componentDidMount以後調用.oop
updateComponent負責管理生命週期中的componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,
render和componentDidUpdate.
若存在componentWillReceiveProps,則執行.
若是此時在componentWillReceiveProps中調用setState,是不會觸發re-render的,而是會進行state合併.
且在componentWillReceiveProps,shouldComponentUpdate和componentWillUpdate中也仍是沒法獲取到更新後的this.state,
即此時訪問的this.state仍然是未更新的數據,所以只有render和componentDidUpdate中才能獲取到更新後的this.stateui
componentWillReceiveProps(nextProps) { console.log(nextProps); if (nextProps.a === 4) { this.setState({ b: 1000 }, () => { console.log(this.state.b); }); } }
unmountComponnet負責管理生命週期中的componentWillUnMount
若是存在componentWillUnMount,則執行並重置全部相關參數,更新隊列以及更新狀態,
若是此時在componentWillUpdate中調用setState,是不會觸發re-render的,這是由於
全部更新隊列和更新狀態都被重置爲null,並清除了公共類,完成了組件卸載操做.this
無狀態組件只是一個render方法,並無組件類的實例化過程,也沒有實例返回.
無狀態組件沒有狀態,沒有生命週期,只是簡單的接受props渲染生成DOM結構,
是一個純粹爲渲染而生的組件.
因爲無狀態組件有簡單,便捷,高效等諸多優勢,因此若是可能的話請儘可能使用無狀態組件.prototype
import React from 'react'; const HelloWorld = (props) => { return ( <div>{ props.a }</div> ); } export default HelloWorld;