在上一章中,要思考一个问题,就是如果dom结构过于复杂的话,渲染dom的时候页面就会变得卡顿,这是因为js是单线程的语言,如果有js代码执行的话,dom渲染就会停滞,等待其他的代码执行完。如果要解决这个问题的话,可以实现一个任务调度器,让浏览器在空闲时间去渲染dom。
window.requestIdleCallback()
可以用来监测浏览器是否有空闲时间,所以可以基于这个api来实现任务调度器
window.requestIdleCallback()
可以接受一个函数,函数中会返回一个[IdleDeadline](<https://developer.mozilla.org/zh-CN/docs/Web/API/IdleDeadline>)
,通过判断 IdleDeadline() < 1
就能判断浏览器是否还有空闲时间
function workLoop(deadline){
let shouldYield = true
while(isWorkOfUtil){
// to do things...
shouldYield = idleDeadline.timeRemaining() < 1
}
requestIdleCallback(workLoop)
}
采用任务调度器的方式来进行dom渲染的话,需要将dom树转化成链表的格式来进行操作,让任务去一个一个的执行。
在转化的时候需要定制规则:
function render(el, container){
fiberOfUnit = {
dom: container,
props: {
children: [ el ]
}
}
}
let fiberOfUnit = null
function workLoop(idleDeadline){
let shouldYield = true
// 利用while来监控空闲时间的剩余,用来决定是否要进行dom渲染
while(shouldYield && fiberOfUnit){
fiberOfUnit = perfromFiberOfUnit(fiberOfUnit)
shouldYield = idleDeadline.timeRemaining() < 1
}
// 递归调用api,检查浏览器是否有空闲时间
requestIdleCallback(workLoop)
}