虚拟DOM(virtual dom)
React本身只是一个DOM的抽象层,使用组件构建虚拟DOM。
What
用JavaScript对象表示DOM信息和结构,当状态变更的时候,重新渲染这个JavaScript的对象结构。这个JavaScript对象称为virtual dom。
Why
DOM操作很慢,轻微的操作都可能导致页面重新排版,非常耗性能。相对于DOM对象,js对象处理起来更快,而却更简单。通过diff算法对比新旧vdom之间的差异,可以批量的、最小化的执行dom操作,从而提高性能。
Where
React中用JSX语法描述视图,通过babel-loader转译后它们变为React.createElement(…)形式,该函数将生成vdom来描述真是dom。将来如果状态变化,vdom将做出相应变化,再通过diff算法对比新老vdom区别从而作出最终dom操作。
JSX
React16原理:babel-loader会预编译JSX为React.createElement(…)
React17原理:react17中的JSX转换不会将JSX转换为React.createElement,而是自动从react的package中引入新的入口函数并调用。
React中的核心API
Component
Render( )
当首次调用时,容器节点里的所有DOM元素都会被替换,后续的调用则会使用react的DOM差分算法(DOM diffing algorithm)进行高效的更新。
如果提供了可选的回调函数,该回调将在组件被渲染或更新之后被执行。
实现react源码 (初次渲染)
- 原生标签节点
- 文本节点
- 函数组件
- 类组件
Index.tsx
Component.
ReactDOM
原生标签节点
函数组件
类组件
Fiber
diffing算法
算法复杂度O(n)
diff策略
- 同级比较,Web UI中DOM节点跨层级的移动操作特比少,可以忽略不计。
- 拥有不同类型的两个组件将会生成不同的属性结构。
例如:div->p
- 开发者可以通过key来按时那些子元素在不同的渲染下能保持稳定。
diff过程
比对两个虚拟dom时会有三种操作:删除、替换和更新
vnode是现在的虚拟dom,newVnode是新虚拟dom。
删除:newVnode不存在时
替换:vnode和newVnode类型不同或key不同时
更新:有相同类型和key但vnode和newVnode不同时
在实践中也证明这三个前提策略是合理且准确的,它证明了整体界面构建的性能。
Fiber
- 为什么需要fiber
对于大型项目,组件树会很大,这个时候递归遍历的成本就会很高,会造成主线程被持续占用,
结果就是主线程上的布局、动画等周期性任务就无法立即得到处理,造成视觉上的卡顿,影响用户体验。
- 任务分解
- 增量渲染(把渲染任务拆分成块,匀到多帧)
- 更新时能够暂停,终止,复用渲染任务
- 给不同类型的更新赋予优先级
- 并发方面新的基础能力
- 更流畅
Fiber链表结构
window.requestIdleCallback(callback[, options])
window.requestIdleCallback()方法将在浏览器的空闲时段内对要调用的函数进行排队。这使开发人员能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数通常以先进先出顺序调用;但是,如果需要,具有指定timeout的回调可能被调用为无序,从而在超时发生之前运行回调。
您可以在空闲回调函数内调用requestIdleCallback(),以便在下一次通过事件循环时安排另一个回调。
callback
当事件循环空闲时,应该在不久的将来调用的函数的引用。回调函数传递一个IdleDeadline对象,该对象描述可用时间量以及是否因为超时期限到期而运行了回调。
options(可选)
包含可选的配置参数。目前只定义了一个属性:
timeout:如果timeout是指定的,具有正值,并且在timeout毫秒已经过去的时间里,回调还没有被调用,则回调将在接下来的空闲时间被调用,即使这样做会导致负面的性能影响。