深入浅出react(二):react15和react16组件生命周期的对比

38 阅读3分钟

一. react组件的设计思想

组件初始化:

render方法 → 生成虚拟DOM → ReactDOM.render方法 → 真实DOM

组件更新:

render方法 → 生成新的虚拟DOM → diff算法 → 定位两次虚拟DOM的差异

react组件的灵魂就是render方法,渲染工作流就是从组件数据改变到组件实际更新的过程。

二. react15的组件生命周期

1. Mounting阶段:组件的初始化渲染挂载

  • constructor():组件挂载之前,state可以在constructor里初始化
  • componentWillMount()render函数生成虚拟Dom之前触发
  • render()render执行过程中不会操作真实的Dom,只是把需要渲染的虚拟Dom返回出来
  • componentDidMount():组件渲染完成,这里可以操作真实Dom,进行异步数据请求

2. Updating阶段:组件更新

  • componentWillReceiveProps():由父组件的更新触发,与props的更新无关
  • shouleComponentUpdate(nextProps,nextState):由组件自身的更新触发,返回一个boolean值,当返回true时,才继续走后面的生命周期,否则不会执行,防止频繁触发render函数,生成新的虚拟Dom,可以用来做性能优化
  • componentWillUpdate()
  • render()
  • componentDidUpdate()

3. 卸载阶段

- componentWillUnmont()

组件销毁的原因:

  • 组件在父组件被移除
  • 组件中设置了key,父组件在render过程中,发现key值和上次不一致

三. react16的组件生命周期

1. Mounting阶段:组件的初始化渲染挂载

  • constructor()
  • getDerivedStateFromProps():使用props来更新state
  • render()
  • componentDidMount()

getDerivedStateFromProps是一个静态方法,声明使用static,访问不到this

static getDerivedStateFromProps(props, state){
  //props:来自父组件的props
  //state:组件自身的state
  return newState
}

getDerivedStateFromProps更新state并不是覆盖,而是对某个属性的更新,返回一个对象格式的值,返回的属性与state原有的属性共存,如果原来state中没有该属性,则新增,如果没有需要更新的时候,返回一个null

2. Updating阶段:组件更新

  • getDerivedStateFromProps()
  • shouleComponentUpdate(nextProps,nextState)
  • render()
  • getSnapshotBeforeUpdate(prevProps, prevState):真实Dom更新之前执行
  • componentDidUpdate()

getDerivedStateFromProps在初始化和更新时都会出现,它并不是用来代替componentWillMount方法的,它是用来替换componentWillReceiveProps的。

强制采用getDerivedStateFromProps来完成props到state的更新,保证生命周期函数的可控,避免大量业务逻辑代码嵌入生命周期,出现不合理的开发错误。

getSnapshotBeforeUpdate的返回值会作为第三个参数给componentDidUpdate,同时获取到更新前的真实DOM和更新前和更新后的State,props信息

getSnapshotBeforeUpdate(prevProps, prevState){
   return 'hhh';
}
componentDidUpdate(prevProps, prevState, valueFromSnapshot){
  // valueFromSnapshot是从getSnapshotBeforeUpdate获取到的值
}

3. 卸载阶段

- componentWillUnmont()

四. Fiber

Fiber是react16对核心算法的重写,使原本同步的渲染过程变成异步的。

react15的渲染过程

每次组件的更新都会构建新的Dom树,通过diff算法与上次的虚拟Dom对比,实现对Dom的更新,是一个递归的过程,且不可打断。一旦渲染开始,线程就无法处理其他交互,页面卡死,降低用户体验。

fiber的渲染过程:

fiber会将一个大的更新任务拆分成小的任务,每执行完一个小任务,渲染暂停,线程会被释放,用来处理优先级更高的事务,避免同步渲染的页面卡死,这就是异步渲染。

react16的生命周期被分为render和commit两个阶段

render阶段在执行过程中允许被打断,因为render过程在页面不可见,不影响用户体验。commit阶段要渲染真实Dom,是同步执行的。

render阶段允许暂停,终止和重启,导致render的生命周期可以被重复执行,所以react16废除掉可能会造成风险的生命周期函数:componentWillMount,componentWillUpdate,componentWillReceiveProps。