类组件中的生命周期函数--React

692 阅读3分钟

今天总结一下 React 中的生命周期函数,主要包括几个常用的生命周期:contructor、render、shouldComponentUpdate、componentDidMount、componentDidUpdate、componentWillUnmount。

首先分阶段看一下各个生命周期函数的执行顺序,在首次渲染过程中,需要执行 constructor、render、componentDidMount,然后如果内部数据或者外部数据改变后就会引起再次渲染,在这一过程中可以用到的生命周期函数主要有 shouldComponentUpdate、componentDidUpdate,在将要销毁的阶段可以使用 componentWillUnmount 函数,见下图所示:

接下来分别总结各个生命周期函数的用途。

一、contructor

该函数是渲染时执行的第一个函数,用来初始化数据,包括内部数据和外部数据,此时不能调用 setState 方法。

二、render

该函数用于展示视图,在 return 后面写要展示的内容,要注意的是只能有一个根元素,如果要展示多个元素,可以用另一个 div 来包裹,但是包裹的 div 同样会渲染到页面上,因此会造成不必要的内存浪费,可以使用 <React.Fragment> 来包裹多个元素,该标签并不会渲染到页面上,为方便该标签也可直接简写为 <>。

三、componentDidMount

该函数在元素插入到页面之后执行,这些代码一般依赖于 DOM,例如要获取一个元素的宽度,就必须在该元素挂载到页面之后才能获取到,同时官方推荐若要发起加载数据的 AJAX 请求最好在此函数中执行。

四、shouldComponentUpdate

该函数主要用于手动判断是否执行 UI 更新,返回 true 表示不阻止 UI 更新,返回 false 则表示阻止 UI 更新,因为在 react 中,一旦改变了值就会触发重新渲染,利用该函数我们就可以根据应用场景灵活地设置返回值,以避免不必要的更新。

在 react 中,由于坚持数据不可变的思想,当我们改变内部数据的时候不能直接修改原有的值,而是重新创建一个新的对象,根据 JavaScript 中对象的特点,重新创建的对象和原有的对象即使内部的值一样,但是两者并不相等,因此在这种情况下 react 总是会触发再次渲染,如下例中,当我们点击按钮后,先执行 n+1 再执行 n-1,其实 n 的值并没有改变,但是却总是会触发 render 函数:

class App extends React.Component{
  constructor(){
    super();
    this.state={
      n:1
    }
  }
  onClick = ()=>{
    this.setState(state=>({n:state.n+1}))
    this.setState(state=>({n:state.n-1}))
  }
  render(){
    console.log("render了")
    return (
      <div className="App">
         {this.state.n}
         <button onClick={this.onClick}>+1</button>
      </div>
    );
  } 
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这个时候我们需要告诉 react 不需要触发重新渲染,因此就要用到 shouldComponentUpdate :

  shouldComponentUpdate(nextProps,nextState){
    if(this.state.n===nextState.n){
      return false;
    }else{
      return true;
    }
  }

该函数的具体用法可查询官方文档。这样做实际上就是对比修改后的 state 中的值和现有 state 中的值是否相等,相等则返回 false,阻止 react 去重新渲染,这个时候你可能会产生疑问,那么每一个值都需要我们去判断吗,react 有没有内置的这种方法自己去判断呢,答案是有的,你可以在定义 class 组件的时候让该组件继承 React.PureComponent,PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key,如果所有 key 的值全都一样,就不会 render,如果有任何一个 key 的值不同,就会 render。

五、componentDidUpdate

该函数在每次视图更新后执行,看起来和 componentDidMount 的作用差不多,但是要注意 componentDidUpdate 在首次渲染的时候并不会执行,而 componentDidMount 在首次渲染的时候要执行,在 componentDidUpdate 中也可以发起 AJAX 请求,用于更新数据,另外要注意在该函数内 setState 的话可能会引起无限循环,所以要加上 if 的判断。如果 shouldComponentUpdate 返回为 false 的话则不会执行该函数。

六、componentWillUnmount

该函数在组件将要被移除页面被销毁时执行,并且 unmount 过的组件不会再次 mount,我们可以利用该函数做一些清理工作,例如在 componentDidMount 中监听的 window scroll、创建的 timer、创建的 AJAX 请求就可以在该函数中取消,减少内存。

若有问题,感谢指正。