野心勃勃的React組件生命周期

jopen 8年前發布 | 20K 次閱讀 React JavaScript開發

當你還在寫著Angular指令,過濾器,注入,服務,提供者,視圖模版的時候,是不是覺得很煩,好在這個時候,React已經神一樣的出現在歷史舞臺。

React組件

React實現了UI=Fn(State)的思想,組件內部有自己的狀態和初始的屬性,組件在某一個時刻都有一個確定的狀態,狀態是不斷變化的,變化的狀態驅動著UI渲染,一切就這么簡單。React讓UI組件化,一個最小的組件實現,需要一個render方法即可。

 1 import React, { Component } from 'react'
 2 var Dialog = React.createClass({
 3     render: function(){
 4         return(
 5             <div>
 6                 Hello React
 7            </div>
 8         )
 9     }
10 })

組件化方便組合重用,組件有自己的生命周期,詳情請閱官方文檔: http://reactjs.cn/react/docs/component-specs.html

讓我們來看看React組件的生命周期:

getDefaultProps: function () {
    return{
        //在組件類創建的時候調用一次,然后返回值被緩存下來。這是第一個觸發的方法,返回的值可以用this.props訪問,此值在所有實例間共享
    }
}
getInitialState: function () {
    return{
        //在組件掛載之前調用一次。返回值將會作為 this.state 的初始值,這是第二個觸發的方法
    }
}
componentWillMount: function(){
    //在初始化渲染執行之前立刻調用,只會調用一次
    //如果在這個方法內調用 setState,render() 將會感知到更新后的 state,將會執行僅一次渲染,盡管 state 改變了。
}
componentWillReceiveProps: function (nextProps){
    //該方法在初始化渲染的時候不會調用
    //在組件接收到新的 props 的時候調用。
    //這個方法里給你在渲染之前根據傳入的屬性來更新狀態的機會
    this.setState({title: nextProps.dialog.get('title')});
}
shouldComponentUpdate: function(nextProps, nextState) {
    //該方法在初始化渲染的時候不會調用, 在使用 forceUpdate 方法的時候也不會。
    //返回布爾值,true表示渲染組件,false表示本次不會運行render渲染調用,默認返回true
    // 在接收到新的 props 或者 state,將要渲染之前調用。
    //如果確定新的 props 和 state 不會導致組件更新,則此處應該 返回 false
}
componentWillUpdate: function (nextProps, nextState) {
    //該方法在初始化渲染的時候不會調用
    //在接收到新的 props 或者 state 之前立刻調用.使用該方法做一些更新之前的準備工作.
    //當shouldComponentUpdate返回true時會在render之前調用.
    //你不能在這個方法中使用 this.setState()。如果需要更新 state 來響應某個 prop 的改變,請使用 componentWillReceiveProps。
}
render: function () {
   //初始化渲染的時候會調用,在第一次初始化渲染的時候不理會shouldComponentUpdate的返回值
   //因為shouldComponentUpdate默認返回true,而第一次初始化渲染時候,shouldComponentUpdate是不會調用的,不管你返回true或false。
   //有點繞,多讀幾遍。
   //當不是初始化渲染時,如果shouldComponentUpdate返回false,則不會調用render方法。
   //在這里可以使用this.props和this.state來獲取數據,請不要在這個方法里改變state
}
componentDidUpdate: function (prevProps, prevState) {
    //該方法在初始化渲染的時候不會調用
    //組件render方法后調用此方法,在組件的更新已經同步到 DOM 中之后立刻被調用,使用該方法可以在組件更新之后操作 DOM 元素。
}
componentDidMount: function(){
   //在初始化渲染執行之后立刻調用,只會調用一次
   //組件已經加載到dom里,在這里可以和瀏覽器交互,直接操作頁面上原始的Dom元素,比如$.ajax調用等等
   window.addEventListener("keydown", this.listenKeyboard, true);
}
componentWillUnmount: function() {
    //在組件從 DOM 中移除的時候立刻被調用。在該方法中執行任何必要的清理,比如無效的定時器,或者清除在 componentDidMount 中創建的 DOM 元素。
    window.removeEventListener("keydown", this.listenKeyboard, true);
}

React組件頁面觸發結果如下:

第一次頁面加載時候組件的生命周期如下:
getDefaultProps -> getInitialState -> componentWillMount -> render ->componentDidMount

如果時在Redux(后面會講到)里加載組件,則生命周期如下:
getDefaultProps -> getInitialState -> componentWillMount -> render ->componentDidMount
-> componentWillReceiveProps -> shouldComponentUpdate

第二次生命周期:
componentWillReceiverProps -> shouldComponentUpdate -> componentWillUpdate -> render
-> componentDidUpdate

如果shouldComponentUpdate返回false,則 componentWillUpdate -> render -> componentDidUpdate這三個方法不會被觸發:
componentWillReceiverProps -> shouldComponentUpdate

父子組件之間通過屬性來傳遞數據,屬性可以是普通字符串也可以是回調函數

兄弟組件之間可以給每個組件設置一個ref屬性,然后同樣可通過屬性來傳遞此ref數據

但是建議不要這么做,這樣結合過于緊密,正確的做法應該是通過消息來解決,

該是Flux出場的時候了,Flux是非死book推的一種解決方案,實現這種方案的框架非常之多,

該是Redux出手的時候了,它是Flux的一種實現,它讓組件之間的交互,狀態的維護變得簡單快樂,簡單快樂,簡單快樂,重要的事重復說三遍。

Redux有一些基本概念

===================================

action:

事件消息對象,有一個必需的type鍵,對消息預處理,可以發起ajax請求數據。然后dispatch消息。

reduce:  

訂閱感興趣的消息type,對消息數據進一步的加工 ,返回的state數據即以props傳入React 組件

component: 

React組件,接受Redux以props傳入的actions和reduce state data,在React組件里用this.props.xxx和this.props.actions.xxx訪問

====================================

組合reduce

====================================

1 import { combineReducers } from 'redux'
2 const reducers = combineReducers({
3     form,
4     items,
5     dialog
6 })

派發的消息,會挨個傳入組合的reduce里,誰對消息感興趣誰就接受此消息即可。

這樣組件之間通過消息通訊,正所謂高內聚低媾合,組件之間不需要彼此知道彼此是誰,我只對數據感興趣,那么數據怎么和組件關聯上的呢,請看下面:

====================================

鏈接component和reduce

====================================

 1 import { bindActionCreators } from 'redux'
 2 import { connect } from 'react-redux'
 3 import * as AllActions from '../actions'
 4 export default connect(state => ({
 5     form: state.form,
 6     items: state.items,
 7     dialog: state.dialog,
 8 }), dispatch => ({
 9     actions: bindActionCreators(AllActions, dispatch)
10 }))(App)

這一步把組件和reduce返回的state鏈接里起來,也就是說dialog reduce返回的數據,是驅動dialog組件的UI更新,這一步比較關鍵,好在redux給你做了,這樣讓狀態的管理特別簡單快樂,簡單快樂,簡單快樂。

React和Flux(Redux)

================================

Redux里用戶在頁面視圖上的交互會觸發dom事件,dom事件會派發消息即action,消息除了必需的type之外還可以攜帶數據,攜帶的數據可以發起服務器請求獲取,然后傳給對這個消息感興趣的reduce,reduce判斷自己對某個消息感興趣后,會對數據進行加工處理,最終返回一個數據對象,即state,返回的state會被Redux作為當前reduce所綁定組件的props傳入React組件內部,在這個時候Redux的事件被React的事件接管進入React組件的生命周期內,React組件觸發React組件的一系列事件方法,當然包括重要的render方法的調用,從而驅動了UI的更新。

在前端JS的歷史舞臺終于革命性的出現了一顆閃耀的新星,野心之大前所未見。

React+Flux讓前端(web+mobile)阿猿們從此變的簡單快樂,簡單快樂,簡單快樂。

來自: http://www.cnblogs.com/CHONGCHONG2008/p/5099483.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!