一. 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。