React從入門到精通系列之(22)React.Component用法

二12、React.Component用法

組件(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前綴的方法在某些事情發生以後被調用。瀏覽器

Mounting(加載組件)

當建立組件的實例並將其插入DOM時,會依次調用這些方法:服務器

  • constructor()網絡

  • componentWillMount()函數式編程

  • render()函數

  • componentDidMount()性能

Updating(更新狀態)

更新能夠由prop或者state的改變引發。在從新渲染組件時依次調用這些方法:

  • componentWillReceiveProps()

  • shouldComponentUpdate()

  • componentWillUpdate()

  • render()

  • componentDidUpdate()

Unmounting(卸載組件)

當從DOM中刪除組件時,將調用此方法:

  • componentWillUnmount()

其餘API

每一個組件還提供了一些其餘API:

  • setState()

  • forceUpdate()

組件屬性

  • defaultProps

  • displayName

  • propTypes

實例內部屬性

  • props

  • state


使用方法

render()

render() {
    // return React Elements
}

注意:render()方法是必須寫的。

當這個方法被調用時,它會檢測this.propsthis.state並返回一個React元素。此元素能夠是本地DOM組件的形式,例如<div/>,也能夠是您本身定義的一個複合組件。

你也能夠返回nullfalse來表示你不想作任何渲染操做。當返回nullfalse時,ReactDOM.findDOMNode(this)將返回null

render()方法應該是純的(pure function,見函數式編程),這意味着它並不會修改組件state,每次調用它時都會返回相同的結果,它不會直接與瀏覽器交互。若是您須要與瀏覽器直接交互,請改用componentDidMount()方法或者其餘生命週期方法來執行你的邏輯。保持render()可讓組件更容易去思考本身應該作什麼。

提示
若是shouldComponentUpdate()返回false,那麼render()不會被執行。


constructor()

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()

componentWillMount()是在裝載(mounting)發生以前被調用。它在render()以前調用,因此在此方法中的設置state不會形成從新渲染。另外,應該避免在此方法中引入有任何反作用的東西(見函數式編程)

在服務器渲染上這是惟一一個調用的生命週期鉤子函數。通常來講,咱們建議使用constructor()


componentDidMount()

componentDidMount()

componentDidMount()在組件裝載到DOM後當即調用。若是須要進行DOM節點的初始化則應該在這裏來執行該邏輯。若是須要從遠程端點加載數據(ajax),那麼這是處理網絡請求的最好地方。在此方法中設置state會去從新渲染DOM。


componentWillReceiveProps()

componentWillReceiveProps(nextProps)

componentWillReceiveProps()在安裝好的組件接收新props以前被調用。 若是你須要更新state用來響應props的更改(例如,重置它),你能夠在此方法中比較this.propsnextProps並使用this.setState()來替換並重置state。

注意,即便props沒有改變,React也能夠調用這個方法,所以若是你只想處理props改變的狀況,請確保比較當前值和下一個值是否不一樣。 當父組件引發你的組件從新渲染時,就有可能會發生這種狀況。

若是你只是調用this.setState(),那麼componentWillReceiveProps()不會被調用。


shouldComponentUpdate()

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實現了propsstate進行淺比較的shouldComponentUpdate()方法。 若是你肯定想人肉處理這個淺比較操做,你能夠本身在這個函數中比較this.propsnextPropsthis.statenextState是否相同。相同返回false,不一樣返回true,那麼React就會根據返回值來確認是否跳過本次DOM渲染。


componentWilUpdate()

componentWillUpdate(nextProps, nextState)

當組件在收到新的props或state時,componentWillUpdate()在渲染以前會當即調用這個方法。 使用這個方法來判斷是非須要從新渲染DOM。 第一次渲染DOM不調用此方法。

注意,this.setState()不會調用此方法。 若是你須要根據state和props來進行從新渲染DOM,請改用componentWillReceiveProps()

note
若是shouldComponentUpdate()返回false,則不會調用componentWillUpdate()


componentDidUpdate()

componentDidUpdate(prevProps, prevState)

componentDidUpdate()在從新渲染DOM以後被調用。 第一次渲染不調用此方法。

當組件已經從新渲染後,此方法是一個執行DOM操做的好機會,同時也是一個處理網絡請求的好地方,前提是你須要比較當前props與以前的props是否相同(例如,若是props沒有改變,那麼可能不須要進行網絡請求)。

note
若是shouldComponentUpdate()返回false,則不會調用componentDidUpdate()


componentWillUnmount()

componentWillUnmount()

componentWillUnmount()在組件被卸載和銷燬以前當即被調用。 此方法能夠執行任何有必要的清理工做,例如清理計時器,取消網絡請求或清理在componentDidMount()中建立的DOM元素。


setState()

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()才能避免沒必要要的從新渲染。


forceUpdate()

component.forceUpdate(callback)

默認狀況下,當組件的state或props改變時,組件將從新渲染。 若是你的render()方法依賴於一些其餘數據,你能夠告訴React組件須要經過調用forceUpdate()來從新渲染。

調用forceUpdate()會致使在組件上調用render(),跳過shouldComponentUpdate() 這將觸發子組件的正常生命週期方法,包括每一個子組件的shouldComponentUpdate()方法。 若是標記更改,React仍將更新DOM。

一般你應該儘可能避免forceUpdate()的全部使用,而且只能從render()中的this.propsthis.state中讀取。


類屬性

defaultProps

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

displayName字符串用於調試消息。 JSX自動設置此值;


propTypes

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!');

實例屬性

props

this.props包含由此組件的調用者定義的props

特別地,this.props.children是一個特殊的props,一般由JSX表達式中的子標籤而不是標籤自己定義。

state

state包含特定於此組件的數據,可能隨時間更改。 state是用戶定義的,它應該是純JavaScript對象。

若是你不在render()中使用它,它不該該設置state。 例如,您能夠將定時器ID直接放在實例上。

永遠不要直接改變this.state,由於調用setState()以後能夠替換你所作的各類變化, 一般應該把this.state看做是不可變的。

相關文章
相關標籤/搜索