組件(Components)
容許您將UI拆分爲獨立的可重用的部分,並單獨的考慮每一個部分。javascript
React.Component
是一個抽象基類。這意味着直接引用React.Component
是毫無心義的。你能夠實現一個它的子類,而且至少定義一個render()
方法便可使用。java
你可使用ES6中class
定義一個React組件:ajax
class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</hr>; } }
若是你尚未使用ES6,你可使用React.createClass()
。編程
每一個組件都有幾個『生命週期方法』,您能夠重寫這些方法,已便在React執行過程當中的指定時間運行本身的代碼。前綴爲Will
的生命週期方法會在在一些事情發生以前被調用,帶有Did
前綴的方法在某些事情發生以後被調用。瀏覽器
當建立組件的實例並將其插入DOM時,會依次調用這些方法:服務器
constructor()
網絡
componentWillMount()
函數式編程
render()
函數
componentDidMount()
性能
更新能夠由prop或者state的改變引發。在從新渲染組件時依次調用這些方法:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
當從DOM中刪除組件時,將調用此方法:
componentWillUnmount()
每一個組件還提供了一些其餘API:
setState()
forceUpdate()
defaultProps
displayName
propTypes
props
state
render() { // return React Elements }
注意:render()
方法是必須寫的。
當這個方法被調用時,它會檢測this.props
和this.state
並返回一個React元素。此元素能夠是本地DOM組件的形式,例如<div/>
,也能夠是您本身定義的一個複合組件。
你也能夠返回null
或false
來表示你不想作任何渲染操做。當返回null
或false
時,ReactDOM.findDOMNode(this)
將返回null
。
render()
方法應該是純的(pure function
,見函數式編程),這意味着它並不會修改組件state,每次調用它時都會返回相同的結果,它不會直接與瀏覽器交互。若是您須要與瀏覽器直接交互,請改用componentDidMount()
方法或者其餘生命週期方法來執行你的邏輯。保持render()
的純
可讓組件更容易去思考本身應該作什麼。
提示
若是shouldComponentUpdate()
返回false
,那麼render()
不會被執行。
constructor(props)
在裝載組件(mounting)以前調用會React組件的構造函數。當實現React.Component
子類的構造函數時,應該在任何其餘語句以前調用super(props)
。不然,this.props
將在構造函數中未定義,這可能致使錯誤。
構造函數是初始化state的標準位置。若是不初始化state,而且不綁定組件內部方法的this指向,則不須要爲React組件實現構造函數。
若是你知道你在作什麼的話,你能夠根據props來初始化state。這裏有一個有效的React.Component
子類構造函數的例子:
constructor(props) { super(props); this.state = { color: props.initialColor }; }
注意這種模式,由於它會將props複製一份在state中,這就可能致使一個意外的bug。因此不該該將props複製到state中。相反,你須要使用提高state
的技巧,該技巧咱們在前面的文章提到過。
若是你使用props複製到state中,你還須要實現componentWillReceiveProps(nextProps)
來保持state是最新的。這個時候使用提高state的方法反而會更容易,也能產生更少的bug。
componentWillMount()
componentWillMount()
是在裝載(mounting)發生以前被調用。它在render()
以前調用,因此在此方法中的設置state不會形成從新渲染。另外,應該避免在此方法中引入有任何反作用的東西(見函數式編程)
。
在服務器渲染上這是惟一一個調用的生命週期鉤子函數。通常來講,咱們建議使用constructor()
。
componentDidMount()
componentDidMount()
在組件裝載到DOM後當即調用。若是須要進行DOM節點的初始化則應該在這裏來執行該邏輯。若是須要從遠程端點加載數據(ajax
),那麼這是處理網絡請求的最好地方。在此方法中設置state會去從新渲染DOM。
componentWillReceiveProps(nextProps)
componentWillReceiveProps()
在安裝好的組件接收新props以前被調用。 若是你須要更新state用來響應props的更改(例如,重置它),你能夠在此方法中比較this.props
和nextProps
並使用this.setState()
來替換並重置state。
注意,即便props沒有改變,React
也能夠調用這個方法,所以若是你只想處理props改變的狀況,請確保比較當前值和下一個值是否不一樣。 當父組件引發你的組件從新渲染時,就有可能會發生這種狀況。
若是你只是調用this.setState()
,那麼componentWillReceiveProps()
不會被調用。
shouldComponentUpdate(nextProps, netState)
使用shouldComponentUpdate()
讓React知道組件是否受當前state或props變化的影響。 默認行爲是在每次state更改時都會去從新渲染DOM,在絕大多數狀況下,你應該依賴於這個默認行爲。
當接收到新的props或state時,shouldComponentUpdate()
在渲染以前被調用。 默認爲true
對於初始渲染或使用forceUpdate()
,不調用此方法。
返回false
不會阻止子組件在state更改時從新渲染。
目前,若是shouldComponentUpdate()
返回false
,那麼將不會調用componentWillUpdate()
,render()
和componentDidUpdate()
。 注意,在未來React能夠將shouldComponentUpdate()
做爲提示而不是嚴格的操做指令
,返回false
仍然可能致使組件的從新渲染。
若是你肯定某些組件在某些操做時有點緩慢,你可讓它繼承React.PureComponent
,而不是繼承React.Component
。
React.PureComponent
實現了props
和state
進行淺比較的shouldComponentUpdate()
方法。 若是你肯定想人肉處理這個淺比較
操做,你能夠本身在這個函數中比較this.props
和nextProps
、this.state
和nextState
是否相同。相同返回false
,不一樣返回true
,那麼React就會根據返回值來確認是否跳過本次DOM渲染。
componentWillUpdate(nextProps, nextState)
當組件在收到新的props或state時,componentWillUpdate()
在渲染以前會當即調用這個方法。 使用這個方法來判斷是非須要從新渲染DOM。 第一次渲染DOM不調用此方法。
注意,this.setState()
不會調用此方法。 若是你須要根據state和props來進行從新渲染DOM,請改用componentWillReceiveProps()
。
note
若是shouldComponentUpdate()
返回false
,則不會調用componentWillUpdate()
。
componentDidUpdate(prevProps, prevState)
componentDidUpdate()
在從新渲染DOM以後被調用。 第一次渲染不調用此方法。
當組件已經從新渲染後,此方法是一個執行DOM操做的好機會,同時也是一個處理網絡請求的好地方,前提是你須要比較當前props與以前的props是否相同(例如,若是props沒有改變,那麼可能不須要進行網絡請求)。
note
若是shouldComponentUpdate()
返回false
,則不會調用componentDidUpdate()
。
componentWillUnmount()
componentWillUnmount()
在組件被卸載和銷燬以前當即被調用。 此方法能夠執行任何有必要的清理工做,例如清理計時器,取消網絡請求或清理在componentDidMount()
中建立的DOM元素。
setState(nextState, callback)
將nextState和當前state進行淺合併。 這是用於從事件處理函數和服務器請求回調中觸發UI從新渲染的主要方法。
第一個參數能夠是一個對象(包含一個或多個要更新的state屬性),也能夠是返回將要引發從新渲染的對象(state和props)。
這裏有一個簡單的用法:
this.setState({myKey: 'my new value'});
它也能夠傳入一個帶有參數的函數function(state,props)=> newState
。 例如,假設咱們想要當前state中的myInteger加上props.step:
this.setState(prevState, props) => { return {myInteger: prevState.myInteger + props.step}; }
第二種參數是回調函數,一旦setState完成而且組件被從新渲染,它就會被執行。 一般咱們建議使用componentDidUpdate()
代替這樣的邏輯。
setState()
不會當即改變this.state
,但會建立並掛起state的修改。 因此在調用此方法中訪問this.state
可能會返回現有值。
不能保證對setState
的因此調用都是同步操做,由於這樣作是爲了將屢次state修改合併爲一次以便提升性能。
setState()
總會從新渲染DOM,除非shouldComponentUpdate()
回false。 若是你正在使用可突變對象,而且沒法在shouldComponentUpdate()
實現條件渲染邏輯,則只有當新state與先前state不一樣時調用setState()
才能避免沒必要要的從新渲染。
component.forceUpdate(callback)
默認狀況下,當組件的state或props改變時,組件將從新渲染。 若是你的render()
方法依賴於一些其餘數據,你能夠告訴React組件須要經過調用forceUpdate()
來從新渲染。
調用forceUpdate()
會致使在組件上調用render()
,跳過shouldComponentUpdate()
這將觸發子組件的正常生命週期方法,包括每一個子組件的shouldComponentUpdate()
方法。 若是標記更改,React仍將更新DOM。
一般你應該儘可能避免forceUpdate()
的全部使用,而且只能從render()
中的this.props
和this.state
中讀取。
defaultProps
是類組件自己的屬性,用來設置類組件的默認props。 能夠用來給未傳入值的props設置默認值。 例如:
class CustomButton extends React.Component { // ... } CustomButton.defaultProps = { color: 'blue'; }
若是props.color
沒有定義,就是將它設置爲默認值blue
:
render() { return <CustomButton />; // props.color will be set to blue }
若是props.color
被設置爲null
,那麼它將會被從新賦值爲null:
render() { return <CustomButton color={null} />; // props.color will remain null }
displayName
字符串用於調試消息。 JSX
自動設置此值;
propTypes
也是類組件自己上的一個屬性,用來規範props應該是什麼類型。 它是從props的名稱到React.PropTypes
中定義的類型的映射。 在開發模式下,當爲prop設置一個不是指定格式的無效值時,會在JavaScript控制檯中顯示警告信息。 在生產模式下,爲了提升效率,不會進行propTypes
檢查。
例如,此代碼確保顏色prop是一個字符串:
class CustomButton extends React.Component { // ... } CustomButton.propTypes = { color: React.PropTypes.string };
咱們建議儘量使用Flow
,以便在編譯時進行類型檢查,而不是在運行時進行類型檢查。 Flow
在React中內置支持,所以能夠輕鬆地在React應用程序上運行靜態分析。
// @flow function foo(x) { return x * 10; } foo('Hello, world!'); // @flow function bar(x): string { return x.length; } bar('Hello, world!');
this.props
包含由此組件的調用者定義的props
。
特別地,this.props.children
是一個特殊的props,一般由JSX表達式中的子標籤而不是標籤自己定義。
state包含特定於此組件的數據,可能隨時間更改。 state是用戶定義的,它應該是純JavaScript對象。
若是你不在render()
中使用它,它不該該設置state。 例如,您能夠將定時器ID直接放在實例上。
永遠不要直接改變this.state
,由於調用setState()
以後能夠替換你所作的各類變化, 一般應該把this.state
看做是不可變的。