版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
PS:轉(zhuǎn)載請(qǐng)注明出處
作者:TigerChain
地址:http://www.itdecent.cn/p/e3d1ecfb6312
本文出自TigerChain簡(jiǎn)書(shū)
git 地址:https://github.com/tigerchain/react-lesson
教程簡(jiǎn)介
- 1、閱讀對(duì)象
本篇教程適合初學(xué)者,老鳥(niǎo)直接略過(guò),如果有誤,歡迎指出,謝謝。
-
2、教程難度
初級(jí)
3、Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/11-lifecycle,如果大家喜歡,麻煩點(diǎn)個(gè) star
正文
1、什么是生命周期
生命周期指的是一個(gè)對(duì)象的生老病死。當(dāng)然生命周期又為廣義和狹義的。具體分為以下幾類。
- 1、動(dòng)物的生命周期:從初生到死亡。
- 2、產(chǎn)品的生命周期:從開(kāi)始到淘汰。(一般指提市場(chǎng)壽命)
- 3、語(yǔ)言或平臺(tái)中某個(gè)組件的生命周期:比如 activity 的生命周期,指的就是 activity 的創(chuàng)建到銷(xiāo)毀的過(guò)程。
- 4、其它生命周周期
2、React 的生命周期
先看 React 的生命周期圖,雖然你可能不理解,通過(guò)后面的學(xué)習(xí)再回頭來(lái)看這幅圖,就會(huì)恍然大悟。

一、這里說(shuō)的 React 的生命周期指的就是 React 組件的生命周期。React Component 通過(guò)定義幾個(gè)函數(shù)來(lái)控制組件在生命周期每個(gè)階段的功能。
總的來(lái)說(shuō) React 組件的生命周期有三種狀態(tài)
1、mounting: 插入真實(shí) DOM </br>
2、updating: 正在被重新渲染 props 或 state 改變 </br>
3、unmounting: 卸載 移除真實(shí) DOM
在 React 中為每個(gè)狀態(tài)又分別提供了兩種處理函數(shù),就是 will 和 did , will 是進(jìn)入狀態(tài)之前調(diào)用的, did 是進(jìn)入狀態(tài)之后調(diào)用的.
總的來(lái)說(shuō),三種狀態(tài)對(duì)應(yīng)不同的函數(shù)
- mounting 對(duì)應(yīng)的函數(shù)
constructor()
componentWillMount()
render()
componentDidMount()
- updating 對(duì)應(yīng)的函數(shù)
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
- unmounting 對(duì)應(yīng)的函數(shù)
componentWillUnmount()
PS:一個(gè)組件中 redner() 方法是必須的。
二、和組件生命周期相關(guān)的函數(shù)有
上面籠統(tǒng)的說(shuō)了一下和組件生命周期相關(guān)的方法,我們下面逐一來(lái)說(shuō)明。
- 1、構(gòu)造函數(shù)
constructor(props, context)
構(gòu)造函數(shù),在組件創(chuàng)建的時(shí)候調(diào)用一次。
- 2、componentWillMount()
void componentWillMount()
在組件掛載之前( render()之前 )調(diào)用。可以用于加載 Loading 條了等操作。
- 3、render
render() ;
render 方法顧名思義,就是渲染的意思,它有一個(gè)返回值,就是返回一個(gè) React 元素(自定義組件或是呈現(xiàn) DOM 組件的元素),當(dāng)然如果你什么也不想返回就可以 return null 或 return false (組件就不顯示了),render() 里面應(yīng)該是純凈的 (不能在里面修改組件的狀態(tài),也不能在里面請(qǐng)求服務(wù)器等耗時(shí)操作[ componentDidMount 方法中進(jìn)行耗時(shí)操作]),只是用來(lái)渲染組件。
- 4、componentDidMount()
void componentDidMount()
在組件掛載之后調(diào)用??梢杂糜诤臅r(shí)操作(請(qǐng)求服務(wù)器或定時(shí)器等)。
- 5、componentWillReceiveProps()
void componentWillReceiveProps(nextProps)
這里的 props 是父組件傳遞給子組件的。父組件發(fā)生 render 的時(shí)候就會(huì)調(diào)用子組件的 componentWillReceiveProps (不管 props 有沒(méi)有更新,也不管父子組件之間有無(wú)數(shù)據(jù)交換),在這個(gè)回調(diào)函數(shù)里面,你可以根據(jù)屬性的變化,通過(guò)調(diào)用this.setState()來(lái)更新你的組件狀態(tài),舊的屬性還是可以通過(guò)this.props來(lái)獲取,這里調(diào)用更新?tīng)顟B(tài)是安全的,并不會(huì)觸發(fā)額外的render調(diào)用。
- 6、shouldComponentUpdate()
bool shouldComponentUpdate(nextProps, nextState)
這個(gè)方法在組件掛載之后,當(dāng)你調(diào)用 setState() 方法的時(shí)候都會(huì)調(diào)用此方法用來(lái)判斷是否要重新渲染組件,如果返回 true 則需要重新渲染,如果是 false 則不會(huì)。我們可以在這個(gè)方法中處理只是數(shù)據(jù)改變,界面不改變的情況,用來(lái)優(yōu)化渲染效率。
- 7、componentWillUpdate()
void componentWillUpdate(nextProps, nextState)
顧名思義,就是組件更新前被調(diào)用的方法,具體是當(dāng) props 和 state 發(fā)生改變的時(shí)候就會(huì)執(zhí)行此方法并且在 redner() 方法之前進(jìn)行。這個(gè)方法也在 shouldComponentUpdate() 方法返回 true 的時(shí)候就會(huì)調(diào)用,返回 false 不會(huì)調(diào)用, 使用此方法為更新前做一些準(zhǔn)備。初始化渲染的時(shí)候不會(huì)調(diào)用這個(gè)方法。
PS:注意一點(diǎn),在這個(gè)方法中不能會(huì)用 this.setState() 方法來(lái)修改狀態(tài)。當(dāng)這個(gè)函數(shù)調(diào)用之后,就會(huì)把 nextProps 和 nextState 分別設(shè)置到 this.props 和 this.nextState 方法中,接著就會(huì)調(diào)用 render() 方法來(lái)渲染了。
- 8、componentDidUpdate()
void componentDidUpdate()
組件渲染后就會(huì)調(diào)用 componentDidUpdate() 方法,但是首次 render() 的時(shí)候是不會(huì)調(diào)用的,首次 render() 的時(shí)候調(diào)用的是 componentDidMount() 方法。
componentWillMount()、componentDidMount 和 componentWillUpdate()、componentDidUpdate 是一一對(duì)應(yīng)的,前者是在掛載的時(shí)候會(huì)被調(diào)用,但是后者是每次更新渲染之后都會(huì)調(diào)用。
- 9、componentWillUnmount()
void componentWillUnmount()
組件被卸載的時(shí)候調(diào)用,一般情況下在 componentWillUnmount() 說(shuō)法中清除注冊(cè)的事件,比如取消定時(shí)器,網(wǎng)絡(luò)請(qǐng)求等。
3、React 中的更新方式
總的來(lái)說(shuō),在 React 中,想要 redner 有以下四種方式。
假使 shouldComponentUpdate 都是返回 true 的情況下
- 1、首次初化 render
- 2、調(diào)用 this.setState() 方法 (我們知道它是異步的,不是每調(diào)用一次 setState 都會(huì)觸發(fā)一次 render ,React 有時(shí)可能會(huì)合并操作,再一次進(jìn)行 render)
- 3、props 發(fā)生改變,但是一般不建議直接調(diào)用 this.setProps()
- 4、手動(dòng)調(diào)用 this.forceUpdate(不推薦這樣使用)
到目前為止,我們大體對(duì) React 組件的生命周期有一個(gè)了解了,下面我們通過(guò) Demo 來(lái)直觀的感覺(jué)一下。
4、實(shí)例演示組件的生命周期
經(jīng)過(guò)上面的學(xué)習(xí),我們大體對(duì) React 組件的生命周期有了一定的認(rèn)識(shí),下面我們寫(xiě)一個(gè) Demo 來(lái)驗(yàn)證一下。
我們可以使用前面學(xué)過(guò)的知識(shí)使用 yarn + webpack + ES6 來(lái)創(chuàng)建項(xiàng)目,如果不懂這些知識(shí),可以看看前面相關(guān)的章節(jié)。以下 Demo 是在 mac 環(huán)境下開(kāi)發(fā)的。
1、打開(kāi)命令行,新建 lifecycle 目錄
mkdir lifecycle
2、進(jìn)入到 lifecycle 文件夾下,并新建 public 和 app 目錄。
cd lifecycle
mkdir public
mkdir app
3、分別在 app 中 和 public 中新建 index.html 和 main.js
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-LifeCycle</title>
</head>
<body>
<div id="container"></div>
<script src="bundle.js"></script>
</body>
</html>
# main.js
import React from 'react' ;
import ReactDOM from 'react-dom' ;
import LifeCycle from './LifeCycle.js' ;
/**
* 定義一個(gè)父組件
*/
class Main extends React.Component{
constructor(props){
super(props) ;
this.state = {
name:'junjun'
}
}
render(){
return(
<LifeCycle
umout={this.unmoutComponent}
name={this.state.name}
testComponentWillReceiveProps={this.changeState.bind(this)}
/>
) ;
}
/**
* 卸載組件
*/
unmoutComponent(){
// 這里卸載父組件也會(huì)導(dǎo)致卸載子組件
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
}
/**
* 通過(guò)修改 state 來(lái)修改 props 用來(lái)測(cè)試 componentWillReceiveProps 方法
*/
changeState(){
this.setState({
name:'TigerChain11111'
})
}
}
ReactDOM.render(
<Main />,
document.getElementById('container')
) ;
在這里我一口氣寫(xiě)完了,注釋非常詳細(xì),如果你學(xué)習(xí)過(guò)前面章節(jié)的知識(shí),那么這個(gè)很容易看懂。
4、在 app 中再新建 LifeCycle.js
# LifeCycle.js
import React, { Component, PropTypes } from 'react';
/**
* 定義一個(gè)生命周期的組件
*/
export default class LifeCycle extends Component {
constructor(props) {
super(props);
console.log("~~ Initial render ~~");
console.log("~~ constructor ~~");
alert("~~ Initial render ~~") ;
alert("~~ constructor ~~") ;
this.state = {
name:'TigerChain'
}
}
/**
* 在掛載之前調(diào)用
*/
componentWillMount(){
console.log("~~ componentWillMout ~~");
alert("~~ componentWillMout ~~") ;
}
render() {
console.log("~~ render ~~");
alert("~~ render ~~") ;
return (
<div>
LifeCycle Demo <p/>
<button onClick={this._changeProps.bind(this)}>changeProps</button><p/>
<button onClick={this._setState.bind(this)}>setState</button><p/>
<button onClick={this._forceWithUpdate.bind(this)}>forceWithUpdate</button><p/>
<button onClick={this._unmout.bind(this)}>unmout</button><p/>
<button onClick={this.koukou.bind(this)}>parentChangeProps</button> <p/>
</div>);
}
/**
* 測(cè)試 ComponentWillReceiveProps 方法
*/
koukou(){
this.props.testComponentWillReceiveProps() ;
}
/**
* 在掛載之后調(diào)用
*/
componentDidMount(){
console.log("~~ componentDidMout ~~");
alert("~~ componentDidMout ~~") ;
}
/**
* 組件掛載之后 當(dāng)調(diào)用 setState() 的時(shí)候 如果此方法返回 true ,則會(huì)重新渲染,否則不會(huì)
*/
shouldComponentUpdate(nextProps, nextState){
console.log("~~ shouldComponentUpdate ~~");
console.log("shouldComponentUpdate nextState",nextState);
alert("~~ shouldComponentUpdate ~~"+nextState) ;
return true ;
}
/**
* props 改變的時(shí)候調(diào)用
*/
componentWillReceiveProps(nextProps){
console.log("~~ componentWillReceiveProps ~~");
alert("~~ componentWillReceiveProps ~~") ;
}
/**
* shouldComponentUpdate 返回 true 的時(shí)候 將要更新
*/
componentWillUpdate(nextProps, nextState){
console.log("componentWillUpdate nextState",nextState);
console.log(this.state.name);
console.log("~~ componentWillUpdate ~~");
alert("~~ componentWillUpdate ~~") ;
}
/**
* 組件已經(jīng)更新
*/
componentDidUpdate(){
console.log("~~ componentDidUpdate ~~");
alert("~~ componentDidUpdate ~~") ;
}
/**
* 組件將要卸載
*/
componentWillUnmount(){
console.log("~~ componentWillUnmount ~~");
alert("~~ componentWillUnmount ~~") ;
}
/**
* 組件卸載的方法
*/
_unmout(){
this.props.umout();
}
_forceWithUpdate(){
this.forceUpdate();
}
/**
* 修改屬性
*/
_changeProps(){
this.setState({
name:'TigerChain1'
})
}
/**
* 修改 state 方法
*/
_setState(){
var that = this ;
if((that.state.name === "TigerChain1") || (that.state.name="TigerChain")){
that.setState({
name:'TigerChainJun'
});
}
}
}
我們?cè)谶@里把組件生命周期的 demo 就寫(xiě)完了,具體可以看注釋。
5、添加 react react-dom babel 等插件依賴
yarn add react react-dom babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0 webpack webpack-dev-server --dev
這里也不多說(shuō),如果不懂的話,可以查看 webpack 這一節(jié)。
6、在項(xiàng)目根目錄新建 .babelrc 文件并輸入以下內(nèi)容
{
"presets": ["react", "es2015","stage-0"]
}
7、在根目錄新建 webpack.config.js 并配置
# webpack.config.js
module.exports = {
entry: __dirname+"/app/main.js",
output:{
path:__dirname + "/public",
filename:"bundle.js"
},
module: {
loaders: [
//babel配置
{
test:/\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
devServer:{
contentBase: "./public",//本地服務(wù)器所加載的頁(yè)面所在的目錄
historyApiFallback: true,//不跳轉(zhuǎn)
inline: true//實(shí)時(shí)刷新
}
}
8、配置腳本 package.json
{
"name": "11-lifecycle",
"version": "1.0.0",
"main": "index.js",
"author": "TigerChain",
"license": "ISC",
"scripts":{
"start":"webpack-dev-server --progress --port 8888"
},
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-0": "^6.22.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"webpack": "^2.3.2",
"webpack-dev-server": "^2.4.2"
}
}
9、運(yùn)行查看 yarn start 并在瀏覽器中輸入 localhost:8888 如果不出什么問(wèn)題,那么我們就可以看到如下界面

圖中就完整的展示了 React 組件的生命周期。我們回過(guò)頭再去看前面的生命周期圖,就能很好的理解了。請(qǐng)大家務(wù)必照著 demo 敲一遍代碼,以便加深理解。(老鳥(niǎo)直接略過(guò))
到此為止,我們的 React 組件的生命周期就講完了。
如果喜歡,就點(diǎn)個(gè)喜歡吧。
Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/11-lifecycle