野心勃勃的React組件生命周期
當你還在寫著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)阿猿們從此變的簡單快樂,簡單快樂,簡單快樂。