react 渲染页面的过程,存在的问题,引入Fiber机制

问题: 渲染过程分为两个阶段
1、调度阶段:根据更新数据生成新的Virtual DOM,通过Diff算法,找出需要更新的元素,生成新的更新队列,
2、渲染过程:遍历更新队列,将变更一次性更新到DOM上。

而1过程是不可控的,也就是说React在执行更新的时候是同步的,浏览器主线程被React占着用来调度,这段时间如果用户进行操作,那就不会得到反馈。需要同步更新的任务完成后,主线程才被释放。

React 是通过递归的方式来渲染组件的,在 V16 版本之前的版本里,当一个状态发生变更时,react会从当前组件开始,依次递归调用所有的子组件生命周期钩子,而且这个过程是同步执行的且无法中断的

解决: Fiber机制
使大量的同步计算被拆解,异步化,使浏览器的主流程得以调控。
每执行完一段更新过程,就把控制权交还给 React 负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有优先级更高的任务,那就去做优先级高的任务。
举例: 潜水员寻宝

实现:
将操作放在栈对象上,在内存中保留栈帧,可以灵活地控制调度过程,比如手动操作栈帧的调用等。
1、将一个state的更新同步任务 拆分成 Fiber任务队列。
2、在任务队列中找到高优先级的Fiber执行,如果执行时间超过了deathLine,则设置为pending状态挂起
3、一个Fiber执行结束或挂起,会调用基于requestIdleCallback/requestAnimationFrame实现的调度器,返回一个新的Fiber任务队列继续进行上述过程

requestIdleCallback会让一个低优先级的任务在空闲期被调用,而requestAnimationFrame会让一个高优先级的任务在下一个栈帧被调用,从而保证了主线程按照优先级执行Fiber单元。

文本框输入 > 本次调度结束需完成的任务 > 动画过渡 > 交互反馈 > 数据更新 > 不会显示但以防将来会显示的任务

ps: js 之所以要同步执行,是因为 js 中可能有输出 document 内容、修改dom、重定向等行为,所以默认同步执行才是安全的。
同步任务: 其实如上所说,state的更新就是同步任务。但为什么又说setState是异步任务呢? React做了性能的优化,将好几次的更新合并成一次,所以就可能是异步更新的。

  • React16更新后的生命周期
    生命周期

从横向看,react 分为三个阶段:

创建时

  • constructor() - 类构造器初始化
  • static getDerivedStateFromProps() - 组件初始化时主动触发
  • render() - 递归生成虚拟 DOM
  • componentDidMount() - 完成首次 DOM 渲染

更新时

  • static getDerivedStateFromProps() - 每次 render() 之前执行
  • shouldComponentUpdate() - 校验是否需要执行更新操作
  • render() - 递归生成虚拟 DOM
  • getSnapshotBeforeUpdate() - 在渲染真实 DOM 之前
  • componentDidUpdate() - 完成 DOM 渲染

卸载时

  • componentWillUnmount() - 组件销毁之前被直接调用
发布了102 篇原创文章 · 获赞 202 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/zr15829039341/article/details/102687923