lznbuild / my-blog

自己的博客
9 stars 1 forks source link

React常见问题 #21

Open lznbuild opened 4 years ago

lznbuild commented 4 years ago

setState详解

React内部实现了一个批量更新,当执行setState时,会将需要更新的state合并后放入状态队列, 把需要更新的nextState push到 pendingStates 队列中,通过 isPending 判断有没有在工作,如果工作了,就更新,否则不更新。

setState在原生事件中,可以在下面直接拿到修改后的值,是同步的。在原生事件中调用setState并不会触发react的批处理机制,所以立即能拿到最新的结果。

在setTimeout,也是同步的。setTimeout回调中使用setState,根据js的异步机制,会将异步代码先暂存,等所有同步代码执行完毕后再执行,这时React的批处理机制已经走完,处理标志isPending被设置为false,这时再调用setState即可立即执行更新,拿到更新后的结果。

虚拟dom有什么特点(优点,缺点)

看到很多人都说,React渲染比操作DOM快,连官网都没这么说过。

React 厉害的地方并不是说它比 操作DOM 快,而是说不管数据怎么变化,都可以以最小的代价来进行更新 DOM。方法就是在内存里用新的数据刷新一个虚拟 DOM 树,然后新旧 DOM 进行比较,找出差异,再更新到 DOM 树上,是只重新渲染差异部分,不是全部更新。

React可真不一定比操作DOM要快。比如只频繁修改一个状态,原生js只需要每次都修改一下改变的内容,而React需要每次都生成新的vdom,跟旧的vdom做对比,再修改差异的部分。

框架的意义在于掩盖底层的 DOM 操作,让开发者用更声明式的方式来描述目的,从而让代码更容易维护。没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的。

优点:

缺点:

比如我在最顶层组件setState一个简单的数据,react就要对整棵树遍历,对比一遍,而用原生操作dom可能一句代码就搞定了,所有就有了shouldComponentUpdate

React 的工作过程

当我们通过render()和 setState() 进行组件渲染和更新的时候,React 主要有两个阶段:

在调度阶段,由于是采用的递归的遍历方式,这种也被成为 Stack Reconciler,主要是为了区别 Fiber Reconciler 取的一个名字。这种方式有一个特点:一旦任务开始进行,就无法中断,那么 js 将一直占用主线程, 一直要等到整棵 Virtual DOM 树计算完成之后,才能把执行权交给渲染引擎,那么这就会导致一些用户交互、动画等任务无法立即得到处理,就会有卡顿,非常的影响用户体验。

把渲染更新过程拆分成多个子任务,每次只做一小部分,做完看是否还有剩余时间,如果有继续下一个任务;如果没有,挂起当前任务,将时间控制权交给主线程,等主线程不忙的时候在继续执行。这种策略叫做 Cooperative Scheduling(合作式调度),操作系统常用任务调度策略之一。

合作式调度主要就是用来分配任务的,当有更新任务来的时候,不会马上去做 Diff 操作,而是先把当前的更新送入一个 Update Queue 中,然后交给 Scheduler 去处理,Scheduler 会根据当前主线程的使用情况去处理这次 Update。为了实现这种特性,使用了requestIdelCallbackAPI。对于不支持这个API 的浏览器,React 会加上 pollyfill。

在上面我们已经知道浏览器是一帧一帧执行的,在两个执行帧之间,主线程通常会有一小段空闲时间,requestIdleCallback可以在这个空闲期(Idle Period)调用空闲期回调(Idle Callback),执行一些任务。

react初次render或协调后所生成的一个对象,react16前是通过组件递归遍历而来,react16是以fiber为节点构建成的单链表结构树,其作为真实dom的映射。 之前,React并没有充分利用调度的优势。更新导致立即重新渲染整个子树。彻底革新React的核心算法以利用调度是Fiber背后的驱动思想

React fiber 的讲解

https://mp.weixin.qq.com/s?__biz=MzI1ODk2Mjk0Nw==&mid=2247484469&idx=1&sn=f68d044f1b0e4e2eb981e3878427b75b&scene=21#wechat_redirect

https://mp.weixin.qq.com/s?__biz=MzI1ODk2Mjk0Nw==&mid=2247484536&idx=1&sn=94777b8c1aab80dffe1fc224bec02c72&scene=21#wechat_redirect

diff算法的策略

react中的自定义组件都要大写?

jsx通过babel的解析,最终都会成为React.createElement(),这里面有个判断,小写开头的是原生html的标签,大写是变量

props不包括ref,key

其他属性会被React添加到子组件的props中,ref,key不会

(持续更新中)