野心勃勃的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)阿猿們從此變的簡單快樂,簡單快樂,簡單快樂。