likes
comments
collection
share

(16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

作者站长头像
站长
· 阅读数 16
转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。

涉及面试题:
 1. 组件生命周期的不同阶段是什么?
 2. React 生命周期方法有哪些?
 3.React v16 中的错误边界是什么?
 4.React v15 中如何处理错误边界?
 5.componentWillMount() 方法中使用 setState() 好吗?
 6. 在 mounting 阶段生命周期方法的执行顺序是什么?
 7.React v16 中,哪些生命周期方法将被弃用?
 8. 生命周期方法 getDerivedStateFromProps() 的目的是什么?
 9. 生命周期方法 getSnapshotBeforeUpdate() 的目的是什么?
10. 在组件类中方法的推荐顺序是什么?
11. 如何在调整浏览器大小时重新渲染视图?
12. 如何监听状态变化?
13. 如何每秒更新一个组件?
14. 为什么不能在 componentWillUnmount 中调用 setState() 方法?
15. 当组件重新渲染时顺序执行的方法有哪些?

编号:[react_16]

1 Initialization

“生命周期函数”是指:在某一时刻,“组件”会自动调用并执行的函数

“生命周期函数”是针对“组件”而言的,每一个“组件”都可以有以下“过程”中所有的“生命周期函数”: (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

接下来,我们结合 TodoList,按程序执行的“过程”,分阶段把“生命周期函数”讲清楚。 ❗️为了便于讲解,请将 TodoList 里的代码同步至《React 入门:⑥ TodoList 代码优化》中的版本。

1️⃣Initialization (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

  • 含义:初始化过程;

  • TodoList 中的代码实现:

/*
🚀constructor 就是我们“初始化”的位置!我们会在这里去定义 state、去接收 props。

❓但,constructor 是不是一个“生命周期函数”呢?
答:
它符合“生命周期函数”的定义——在某一时刻,“组件”会自动调用并执行的函数。
所以,从某方面来说,我们可以把它理解为“生命周期函数”。
但是,constructor 不是 React 所独有的,它是 ES6 语法中自带的一个函数。
故,严格来说,我们不把它归类到 React 的“生命周期函数”里。
 */
constructor(props) {
  super(props);
  this.state = {
    inputValue: "", 
    list: []
  };
}

2 mounting

2️⃣mounting (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

  • 含义:组件“挂载”到页面上的过程;

  • TodoList 中的代码实现:

import React, { Component, Fragment } from "react"; 

import TodoItem from "./TodoItem"; 

import "./style.css"; 

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: "", 
      list: []
    };
    
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleBtnClick = this.handleBtnClick.bind(this);
    this.handleItemDelete = this.handleItemDelete.bind(this);
    
  }

  componentWillMount() { /*
  											 2️⃣-①:这个“生命周期函数”是在“组件”
                         即将被“挂载”到页面的时刻自动执行;
                          
                         ❓什么是“挂载”?
                         答:“挂载”指“组件”第一次被放在页面的时候。
                          
                         ❗️故:一般来说,一个组件在页面上展示的时候,
                         componentWillMount 只会执行一次(“挂载”的这个阶段)!
                          */
    
    console.log("componentWillMount") 
  }
  
  render() { // 2️⃣-②:这个“生命周期函数”是去做“组件”的“挂载”;
    console.log("parent render")
    
    return(
      <Fragment>
        <div>
          <label htmlFor="insertArea">请输入要进行的事项:</label>    
        
          <input 
            id="insertArea"
      
            className="input"
            value={this.state.inputValue}
            onChange={this.handleInputChange}
          />

          <button onClick={this.handleBtnClick}>
            提交
          </button>
        </div>

        <ul>
          {this.getTodoItem()}
        </ul>

      </Fragment>
    )
  }
  
  componentDidMount() { /*
  											2️⃣-③:这个“生命周期函数”是在“组件”
  											被“挂载”到页面之后自动执行;
                         
                        ❗️一般来说,一个组件在页面上展示的时候,
                        componentDidMount 也只会执行一次(“挂载”的这个阶段)!
                         
                        🏆请一定注意这个特点,下下篇文章,
                        我们会利用“只执行一次”这个特性,去进行 AJAX 数据的请求。
                         */
  
  	console.log("componentDidMount")  
  }

  getTodoItem() {
    return this.state.list.map((item, index) => { 
      return( 
        <TodoItem 
        	key={index}
        
        	content={item}
        	index={index} 
        	itemDelete={this.handleItemDelete}
        />  
      )  
    })
  }
  
  handleInputChange(e) {
    const value = e.target.value
    
    this.setState(() => ({
      inputValue: value
    }))
  }

  handleBtnClick() {
    this.setState((prevState) => ({
      list: [...prevState.list, prevState.inputValue],  
      inputValue: ""        
    }))
  }

  handleItemDelete(index) { 
    this.setState((prevState) => {
      const list = [...prevState.list]
      list.splice(index, 1)
        
      return {list}
 
    })
  }
}

export default TodoList;

看下页面的控制台(当组件成功“挂载”到页面后,再进行相关操作时, componentWillMountcomponentDidMount 都不再执行,但 render 会执行): (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

3 Updation

3️⃣Updation (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

  • 含义:组件“更新”的过程,即“数据”——state、props 发生变化的时候,页面的“更新”会被执行的过程;

  • TodoList 中的代码实现:

❗️我们先讲 props 和 states 发生变化时,它们所共有的“生命周期函数”的执行逻辑。 (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

import React, { Component, Fragment } from "react"; 

import TodoItem from "./TodoItem"; 

import "./style.css"; 

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: "", 
      list: []
    };
    
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleBtnClick = this.handleBtnClick.bind(this);
    this.handleItemDelete = this.handleItemDelete.bind(this);
    
  }

  componentWillMount() {
    
    console.log("componentWillMount") 
  }
  
  render() { 
    console.log("parent render")
    
    return(
      <Fragment>
        <div>
          <label htmlFor="insertArea">请输入要进行的事项:</label>    
        
          <input 
            id="insertArea"
      
            className="input"
            value={this.state.inputValue}
            onChange={this.handleInputChange}
          />

          <button onClick={this.handleBtnClick}>
            提交
          </button>
        </div>

        <ul>
          {this.getTodoItem()}
        </ul>

      </Fragment>
    )
  }
  
  componentDidMount() {  
  
    console.log("componentDidMount")  
  }

	shouldComponentUpdate() { /*
  													3️⃣-①:这个“生命周期函数”是在“组件”
  													被“更新”之前,会被自动执行;
                             */
    
  	console.log("shouldComponentUpdate")
  }

  getTodoItem() {
    return this.state.list.map((item, index) => { 
      return( 
        <TodoItem 
        	key={index}
        
        	content={item}
        	index={index} 
        	itemDelete={this.handleItemDelete}
        />  
      )  
    })
  }
  
  handleInputChange(e) {
    const value = e.target.value
    
    this.setState(() => ({
      inputValue: value
    }))
  }

  handleBtnClick() {
    this.setState((prevState) => ({
      list: [...prevState.list, prevState.inputValue],  
      inputValue: ""        
    }))
  }

  handleItemDelete(index) { 
    this.setState((prevState) => {
      const list = [...prevState.list]
      list.splice(index, 1)
        
      return {list}
 
    })
  }
}

export default TodoList;

在页面控制台查看一下打印出来的信息: (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

❌注意看页面的“警告”: shouldComponentUpdate 函数需要返回一个“布尔值”。

为什么呢?从单词结构就可以看出,这是在“询问”我们:组件需要被“更新”吗?

  • true:更新,继续下一个“生命周期函数”的执行,页面产生相应的反馈;
  • false:不更新,后边的“生命周期函数”不再执行,页面不产生任何的反馈。

💡一般情况下,这里都是 true ,我们下篇文章会讲解 false 的用法(用于提高“组件”的性能)。

回到 TodoList.js 文件,继续讲解:

import React, { Component, Fragment } from "react"; 

import TodoItem from "./TodoItem"; 

import "./style.css"; 

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: "", 
      list: []
    };
    
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleBtnClick = this.handleBtnClick.bind(this);
    this.handleItemDelete = this.handleItemDelete.bind(this);
    
  }

  componentWillMount() {
    
    console.log("componentWillMount") 
  }
  
  render() { /*
             3️⃣-③:“生命周期函数”render 会执行,根据变化了的“数据”,
             重新“更新”页面;
              */
    console.log("parent render")
    
    return(
      <Fragment>
        <div>
          <label htmlFor="insertArea">请输入要进行的事项:</label>    
        
          <input 
            id="insertArea"
      
            className="input"
            value={this.state.inputValue}
            onChange={this.handleInputChange}
          />

          <button onClick={this.handleBtnClick}>
            提交
          </button>
        </div>

        <ul>
          {this.getTodoItem()}
        </ul>

      </Fragment>
    )
  }
  
  componentDidMount() {  
  
    console.log("componentDidMount")  
  }

  shouldComponentUpdate() { /*
  													3️⃣-①:这个“生命周期函数”是在“组件”
                            被“更新”之前,会被自动执行;
                             */
    
    console.log("shouldComponentUpdate")
    return true
    
  }

  componentWillUpdate() { /*
  												3️⃣-②:这个“生命周期函数”是在“组件”
                          被“更新”之前,shouldComponentUpdate 询问之后,
                          且得到 true 的“答复”后,才自动执行;
                           */
  
    console.log("componentWillUpdate")
  }

  componentDidUpdate() { /*
  											 3️⃣-④:这个“生命周期函数”是在“组件”
                         被“更新”完成之后,会自动执行。
                          */
    
    
    console.log("componentDidUpdate")
  }

  getTodoItem() {
    return this.state.list.map((item, index) => { 
      return( 
        <TodoItem 
        	key={index}
        
        	content={item}
        	index={index} 
        	itemDelete={this.handleItemDelete}
        />  
      )  
    })
  }
  
  handleInputChange(e) {
    const value = e.target.value
    
    this.setState(() => ({
      inputValue: value
    }))
  }

  handleBtnClick() {
    this.setState((prevState) => ({
      list: [...prevState.list, prevState.inputValue],  
      inputValue: ""        
    }))
  }

  handleItemDelete(index) { 
    this.setState((prevState) => {
      const list = [...prevState.list]
      list.splice(index, 1)
        
      return {list}
 
    })
  }
}

export default TodoList;

返回页面控制台查看打印信息: (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

接着,我们来看看 3️⃣中,props 和 states 不一样的部分—— componentWillReceiveProps(16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

❓这个“生命周期函数”特殊在哪呢? 答:

TodoList 是一个“顶层组件”,它并没有接收任何 props 。接收 props 最多的是 TodoItem 组件。即,这个“生命周期函数”只对拥有 props 参数的 TodoItem 组件生效。

打开 TodoItem.js 文件:

import React, { Component } from "react";

class TodoItem extends Component {
  constructor(props) {
    super(props);
    
    this.handleClick = this.handleClick.bind(this);
  } 
  
  render() {
    const {content} = this.props
    
    return(
      <div onClick={this.handleClick}> 
        {content}  
      </div>
    )
  }
  
  handleClick() {  
    const {itemDelete, index} = this.props
    
    itemDelete(index)
  }

  componentWillReceiveProps() { /*
  															❗️❗️❗️这个“生命周期函数”要执行,需同时满足以下条件:
                                ①:这个组件要从父组件接收“参数”;
                                ②:如果这个组件“第一次”存在于父组件中,这个“生命周期函数”不会执行;
                                ③:如果这个组件之前已经存在于父组件中,这个“生命周期函数”才会执行。
                                 */
  
    console.log("child componentWillReciveProps")
  }
}

export default TodoItem;

返回页面控制台查看打印信息: (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

4 Unmounting

4️⃣Unmounting (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

  • 含义:把“组件”从页面上去除的过程;

  • TodoList 中的代码实现(打开 TodoItem.js 文件):

import React, { Component } from "react";

class TodoItem extends Component {
  constructor(props) {
    super(props);
    
    this.handleClick = this.handleClick.bind(this);
  } 
  
  render() {
    const {content} = this.props
    
    return(
      <div onClick={this.handleClick}> 
        {content}  
      </div>
    )
  }
  
  handleClick() {  
    const {itemDelete, index} = this.props
    
    itemDelete(index)
  }

  componentWillReceiveProps() { 
    console.log("child componentWillReciveProps")
  }

	componentWillUnmount() { /*
  												 ❗️❗️❗️这个“生命周期函数”是在“组件”
  												 即将被程序从页面上剔除时,会自动执行。
                            */
  
  	console.log("child componentWillUnmount")
  }

}

export default TodoItem;

返回页面控制台查看打印信息: (16)React 进阶——⑥ React 生命周期函数(上):弄懂所有“生命周期函数” | React 基础理论实操

祝好,qdywxs ♥ you!

转载自:https://juejin.cn/post/7290732297427058743
评论
请登录