14、React系列之--組件的生命周期

版權(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ò),如果有誤,歡迎指出,謝謝。

正文

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ì)恍然大悟。

ReactLifeCycler.jpeg

一、這里說(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)題,那么我們就可以看到如下界面

lifecycle.gif

圖中就完整的展示了 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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容