先了解一些基础知识
屏幕刷新率
一般电脑刷新率是60次/s,而页面是一帧一帧渲染的,而当帧数达到60时,页面就是流畅的,而小于这个值时,用户就会感觉到卡顿。浏览器刷新频率一般和屏幕一样,因为有一个vSync标记符,显卡会在每一帧开始时间给浏览器窗口发送一vSync标识符。
帧
每个帧的开头包括样式计算,布局,绘制,js引擎和页面渲染引擎是在同一个渲染线程,而页面渲染引擎(GUI)和js引擎是互斥的,如果某个任务执行时间过长,浏览器就会推迟渲染,从而造成卡顿,react16就解决了这个问题。
一帧做的事,输入事件,执行js,开始帧,执行requestAnimationFrame,再布局,绘制,到空闲时间。
rAf
requestAnimationFrame回调函数会在绘制前调用,
可以看到浏览器的每帧刷新时间就是大概16ms,标准是16.6ms
requestldleCallback
我们希望快速响应用户,让用户觉得够快,不阻塞交互,requestldleCallback可以是开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应,正常帧任务完成后没超过16ms,说明由空闲时间,就会执行requestldleCallback里注册的任务。简单的说就是requestIdleCallback里的回调函数优先级比较低,请求浏览器在空闲的时候再帮我执行。后面可以跟第二个参数对象{timeout: 1000} 意思是即使没时间,1s后也要帮我执行
如图,requestdleCallback会申请时间片,浏览器在每一帧的时候先做自己的事情,有空闲时间才会分配时间片执行回调,若不够时间就不会执行。
react16的fiber就是这样执行的,将一个任务拆分为多个任务,当这一帧执行完还有时间时就会继续执行,若没时间,就会将线权换给浏览器,避免造成js引擎执行太久而gui引擎没执行导致的页面空白卡顿问题。
如图,requestIdleCallback的使用
创建一个睡眠函数,还有一个任务。该任务里拆分为三个小任务。
requestIdleCallback会给回调函数传入一个对象,该对象的属性可以判断当前帧有无剩余时间,当前帧是否超时,再以此判断是否要继续执行任务,如果超时就把线权还给浏览器。这样就将一个大的任务拆分为几个小的任务并且使用requestIdleCallback进行优化。
单链表
单链表是一种链式存取的数据结构。
在Fiber中,有很多用到单链表的地方。
头指针指向尾。
接着我们手写是线下单链表
定义每个state,也就是每个节点,这个节点有自己的数据payload,还有指针nextUpdate,
接着定义一个列表类。(单链表)
我们想在这个链表实现进栈操作,然后逐代更新我们的state。
以setState为例子,我们想每次都更新state的值,单链表的操作就是将其作为一个节点塞进列表。上面是向其中塞入4个节点,
所以我们要实现这个方法,很简单那的将头尾指针相连就好。
接着要逐步更新我们的state值
从第一个节点开始遍历,因为我们传入的state可能是函数,所以要做额外处理,接着再使用浅复制更新state的值,最后遍历完再清空列表。
这样单链表就完成了,相当于模拟setState的操作。
number从一开始的0变成2,成功。
未完待续。。。。