虚拟DOM生成dom
Chunbin Lv4

render

使用方法

1
React.render(<App/>,document.getElementById('root'))

<App/>挂载到root节点上

1
2
3
4
5
6
7
8
9
10
11
12
13
export function render(
element, // 虚拟DOM
container, // 挂载的节点
callback, // render是有回调的
) {
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
}

调用了legacyRenderSubtreeIntoContainer函数

legacyRenderSubtreeIntoContainer

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
function legacyRenderSubtreeIntoContainer(
parentComponent: ?React$Component<any, any>, // 父节点
children: ReactNodeList, // 子节点
container: Container, // 挂载节点
forceHydrate: boolean, // 是否Hydrate
callback: ?Function,
) {
let root: RootType = (container._reactRootContainer: any);
let fiberRoot;
// 第一次调用的时候传是dom节点,不存在_reactRootContainer属性
if (!root) {
// Initial mount
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
container,
forceHydrate,
);
fiberRoot = root._internalRoot;
if (typeof callback === 'function') {
const originalCallback = callback;
callback = function() {
const instance = getPublicRootInstance(fiberRoot);
originalCallback.call(instance);
};
}
// Initial mount should not be batched.
unbatchedUpdates(() => {
updateContainer(children, fiberRoot, parentComponent, callback);
});
} else {
fiberRoot = root._internalRoot;
if (typeof callback === 'function') {
const originalCallback = callback;
callback = function() {
const instance = getPublicRootInstance(fiberRoot);
originalCallback.call(instance);
};
}
// Update
updateContainer(children, fiberRoot, parentComponent, callback);
}
return getPublicRootInstance(fiberRoot);
}

一阵追踪后从react-reconciler/src/ReactFiberReconciler调用了createContainer
再一阵追踪调用了从ReactFiberRoot.new.js调用了
createFiberRoot->
new FiberRootNode创建一个根fiber节点 ->
createHostRootFiber创建后续节点并放在root的current里->返回了一个fiber节点

updateContainer

然后我们来看看updateContainer做了什么,在ReactFiberReconciler.js中我们找到了这个方法

1
2
3
4
5
6
7
8
//  创建了update
const update = createUpdate(expirationTime, suspenseConfig);
update.payload = {element};

// 把update推到cureent的更新队列
enqueueUpdate(current, update);
// 调度
scheduleWork(current, expirationTime);

Update的结构:
tag:更新类型,UpdateState、ReplaceState、ForceUpdate、CaptureUpdate
payload:状态变更函数或新状态本身
callback:回调,作用于 fiber.effectTag,并将 callback 作为 side-effects 回调
expirationTime:deadline 时间,未到该时间点,不予更新
suspenseConfig:suspense 配置
next:指向下一个 Update
priority:仅限于 dev 环境

updateQueue的结构:
baseState:先前的状态,作为 payload 函数的 prevState 参数
baseQueue:存储执行中的更新任务 Update 队列,尾节点存储形式
shared:以 pending 属性存储待执行的更新任务 Update 队列,尾节点存储形式
effects:side-effects 队列,commit 阶段执行

scheduleWork

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量