2025-05-15 日报 Day187

2025-05-15 日报 Day187

Yuyang 前端小白🥬

今日的鸡汤

巨大的用户群体绝不仅意味着金山银山,还意味着责任如山。

今日学习内容

1、https://www.youtube.com/watch?v=EVFZazcxAbo&t=4112s

今日笔记

Commit阶段工作流简析

  • before mutation阶段,这个阶段DOM节点还没有被渲染到界面上去
  • mutation,这个阶段负责DOM节点的渲染
  • layout,这个阶段处理DOM渲染完毕之后的收尾逻辑
    它还会把fiberRoot的current指针指向workInProgress Fiber树

performSyncWorkOnRoot
workLoopSync
performUnitOfWork
beginWork
completeWork
completeUnitOfWork
reconcileChildFibers

concurrent模式(异步渲染)下的“时间切片”和“优先级”实现

“双缓存”模式
在React中双缓冲模式能够帮我们较大限度地实现Fiber节点的复用从而减少性能方面的开销

completeWork的工作原理:
current树与workInProgress树可以对标“双缓存”模式下的两套缓冲数据:
当current树呈现在用户眼前时,所有的更新都会由workInProgress树来承接
workInProgress树将在内存里完成改变

时间切片关键代码片段:

1
2
3
4
5
function workLoopConcurrent() {
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}

shouldYield() 是 时间切片的核心判断条件。

1
2
3
function shouldYieldToHost() {
return getCurrentTime() >= deadline;
}

deadline 是当前帧的截止时间(由 requestAnimationFrame 或 MessageChannel 推动),当当前时间超过 deadline,就会返回 true,中断渲染,让出主线程。
[开始构建 Fiber 树]

[workLoopConcurrent]

while (workInProgress && !shouldYield()) {

performUnitOfWork(unit)
}

[如果 shouldYield() === true]
→ 让出主线程
→ 等下一帧继续(通过 MessageChannel 触发 flushWork)

优先级调度:

  • 通过调用unstable_scheduleCallback来发起调度
  • 结合任务的优先级信息为其执行不同的调度逻辑

源码解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
function unstable_scheduleCallback(priorityLevel, callback, options){
// 获取当前时间
var currentTime = exports.unstable_now();
// 声明startTime,startTime是任务的预期开始时间
var startTime;

// 以下是对options入参的处理
if(typeof options === 'object' && options !== null){
var delay = options.delay;

// 若入参规定来延迟时间,则累加延迟时间
if(typeof delay === 'number' && delay > 0){
startTime = currentTime + delay;
} else {
startTime = currentTime;
}
}else{
startTime = currentTime;
}

// timeout 是 expirationTime的计算依据
var timeout;

// 根据priorityLevel,确定timeout的值
switch(priorityLevel){
case ImmediatePriority:
timeout = IMMEDIATE_PRIORITY_TIMEOUT;
break;
case UserBlockingPriority:
timeout = USER_BLOCKING_PRIORITY_TIMEOUT;
break;
case NormalPriority:
timeout = NORMAL_PRIORITY_TIMEOUT;
break;
case LowPriority:
timeout = LOW_PRIORITY_TIMEOUT;
break;
case IdlePriority:
timeout = IDLE_PRIORITY_TIMEOUT;
break;
default:
throw new Error('Unknown priority level.');
}

var expirationTime = startTime + timeout;

// 创建task对象
var newTask = {
id: ++taskIdCounter,
callback: callback,
priorityLevel: priorityLevel,
startTime: startTime,
expirationTime: expirationTime,
sortIndex: -1, // 用于排序的索引
}

// 若当前时间小于开始时间,说明该任务可延时执行
if(startTime > currentTime){
// 将未过期任务推入"timerQueue"
newTask.sortIndex = startTime;
push(timerQueue, newTask);

// 若taskQueue中没有可执行的任务,而当前任务又是timerQueue中的第一个任务
if(peek(taskQueue) === null && peek(timerQueue) === newTask) {
....
// 那么就派发一个延时任务,这个延时任务用于检查当前任务是否过期
requestHostTimeout(handleTimeout, startTime - currentTime);
}
}else{
// else里处理的是当前时间大雨startTime的情况,说明这个任务已过期
newTask.sortIndex = expirationTime;
push(taskQueue, newTask);
requestHostCallback(flushWork);
}
return newTask;
}

image-20250708085922356

image-20250708090007395

image-20250708090249723

此页目录
2025-05-15 日报 Day187