初探 React 組件生命週期
組件
React
提供React.Component
,我們可以透過使用組件,拆分 UI 為可以重複使用的獨立部分。React.Component
是一個抽象的 base class。我們甚少直接運用React.Component
,通常是透過創建一個子類,並使用render()
方法。
例子:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
如果你不選擇使用 ES6,你可以使用模組create-react-class
。你可以參考React Without ES6。
下面這一段和 ES6 的寫法效果一樣:
var createReactClass = require('create-react-class');
var Greeting = createReactClass({
render: function() {
return <h1>Hello, {this.props.name}</h1>;
}
});
組件生命週期
每一個組件都會有幾個生命週期的方法,你可以在程序運行的指定時間,透過覆蓋他們來運行特定代碼。對於這些方法,我們會用will-
來表示它會在某些事情發生之前的一刻被調用,而did-
則是表示它會在某些事情發生之後的一刻被調用。本文會細說加載組件中發生了什麼事情。
加載 (Mounting)
constructor()
componentWillMount()
render()
componentDidMount()
更新 (Updating)
當 props 或者 state 更新的時候,下面這些方法會被調用:
- componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
斷開連接 (Unmounting)
當組件脫離 DOM 的時候,下面這個方法回被調用:
- componentWillUnmount()
其他內置方法
- setState()
- forceUpdate()
我們會在下文討論一下 React 是如何加載組件。
{% img /img/react-mount.svg 300 auto React LifeCycle Mount %}
constructor()
constructor(props)
在 React 加載組件之前,它會調用constructor
。你可以在constructor
中去賦予組件的初始state
。如果你使用props
創造初始state
的話,這也是可以接受的。這會很有效地fork
組件的props
,然後賦予初始state
的值。
有效的constructor
例子:
constructor(props) {
super(props);
this.state = {
color: props.initialColor
};
}
注意事項
- 如果你不需要賦予初始
state
,你不需要在 React 的組件中植入constructor
。 - 當你使用在
React.Component
的子類中加載constructor()
方法時,你應該第一時間調用super(props)
,而不是在任何 statement 之後。不然,我們獲取this.props
值的時候,它會是undefined
。 - 在一些類似上面的例子,
state
未必會及時與任何的props
更新。如果你需要同步state
的話,你其實是想要lift the state up。
componentWillMount()
componentWillMount()
它會在組件render()
之前執行一次,然後不能再執行。如果在這裡定義了setState
方法,頁面只會在加載之前更新一次,不會重複渲染。React 官方推薦使用constructor()
代替這個方法。
render()
React.Component
必須有這個方法,即使你返回null
,或者false
。當你返回null
,或者false
的時候,ReactDOM.findDOMNode(this)
會返回null
。
當它被調用的時候,它會檢查this.props
和this.state
,然後返回一個單獨的 React 元素。這個元素會是一個純正的DOM
組件,例如
注意事項
render()
方法應該是pure
:它不會改寫任何組件的state
。每一次調用它都會返回同樣的結果。它不會直接接觸到瀏覽器層面。- 如果你需要接觸到瀏覽器層面,你應該在
componentDidMount()
或者其他生命週期方法中接觸瀏覽器。 - 保持
render()
方法 pure 來讓組件更加容易被人理解。
componentDidMount()
componentDidMount()
它會在組件加載之後執行一次。如果你的初始程序需要 DOM nodes,你應該在這裡寫。如果你需要從其他地方加載資料,這裡也是一個不錯的地方去執行網絡請求。如果在這裡定義了setState
方法,會觸發重複渲染。
測試代碼
class Greeting extends React.Component {
_log(method, args) {
console.log(method, args);
}
constructor(props) {
super(props);
console.log('constructor', props);
}
render() {
this._log('render', this.props.name);
return <h1>Hello, {this.props.name}</h1>;
}
componentWillMount() {
this._log('componentWillMount');
}
componentDidMount() {
this._log('componentDidMount');
}
}
ReactDOM.render(
<Greeting name="Calpa" />,
document.getElementById('app')
);
Console Output:
"constructor" Object {
name: "Calpa"
}
"componentWillMount" undefined
"render" "Calpa"
"componentDidMount" undefined
你可以在CodePen中獲取,並測試這段代碼。
不知道拿哪一張當封面好。。。