大家好,我是前端西瓜哥。今天来学习 React 中的调和器 Reconciler。
目前成都创新互联已为1000多家的企业提供了网站建设、域名、雅安服务器托管、网站托管维护、企业网站设计、察哈尔右翼前网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
React 的版本为 18.2.0
ReactElement 就是 React.createElement() 方法的返回结果,一种 映射真实 DOM 层级关系的对象,但里面可以带上组件元素。通常我们会用 JSX 去写。
类组件的 render 方法的返回值和函数组件的返回值都是 ReactElement。
fiber 是一个节点,是 React Fiber 时间分片架构中的一个节点。fiber 是 ReactElement 和真实 DOM 的桥梁。
fiber 会根据 ReactElement 构建成一棵树。当更新时,组件会调用 render 方法生成新的 ReactElement,然后我们再构建一个新的 Fiber 树,和旧树对比。
fiber 树下的 fiber 节点通过下面三个字段进行关联:
一个 App 组件的 fiber 树结构:
App 的 child 是会指向它创建的 element 对应 fiber 的根节点。
在调用 createRoot(并发模式)或者 ReactDOM.render(同步模式)时,会执行 createFiberRoot 方法。
function createFiberRoot(containerInfo, tag) {
// 生成 fiberRoot。containerInfo 是挂载根节点(比如 div#root)
const root = new FiberRootNode(containerInfo, tag);
// 生成 rootFiber
const uninitializedFiber = createHostRootFiber(tag);
// 互相关联
root.current = uninitializedFiber;
uninitializedFiber.stateNode = root;
return root;
}
createFiberRoot 创建一个了 fiberRoot,以及一个 rootFiber。它们的关系如下:
一个 fiberRoot 是 fiber 树的根节点的维护者,是 fiberRootNode 实例,通过 current 确定要使用哪一棵 fiber 树。
每调用 createRoot 都会构建新的 fiber 树,并生成一个新的 fiberRoot 去指向它。
rootFiber 是一颗 fiber 树的根节点,也属于是 fiber 节点。rootFiber 通过属性 stateNode 访问到 fiberRoot。注意不是 return,因为 fiberRoot 的结构完全不一样,不是 fiber 节点。
creatRoot 方法返回的是个对象,它的 _internalRoot 属性指向的是这个 fiberRoot。
在 workLoopSync 或 workLoopConcurrent 中,是会不断地调用 performUnitOfWork(workInProgress) 的。
这个函数会不断地处理以 fiber 为单位的任务。
workLoopConcurrent 的实现:
function workLoopConcurrent() {
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}
看看 performUnitOfWork 的核心实现:
function performUnitOfWork(unitOfWork) {
// 拿到当前 fiber 节点的 “替身”
var current = unitOfWork.alternate;
var next = beginWork(current, unitOfWork, subtreeRenderLanes); // 递
if (next === null) {
completeUnitOfWork(unitOfWork); // 归
} else {
workInProgress = next;
}
}
performUnitOfWork 由两部分组成:
还是这个 fiber 树的图,这里的粉色的 1、2、4 表示的是 beginWork,3、5 则代表 completeUnitOfWork。
performUnitOfWork 中,先调用 beginWork。
beginWork 的作用是,自上而下根据组件进行组件实例化,根据新的 element 构建 fiber,给旧的 fiber 打上 effectTag。
function beginWork(current, workInProgress, renderLanes) {
if (current !== null) {
const oldProps = current.memoizedProps;
const newProps = workInProgress.pendingProps;
}
// 根据不同类型的组件,进行不同的操作
switch (workInProgress.tag) {
// ...
case ClassComponent: {
const Component = workInProgress.type;
// 未处理的新 props 对象
const unresolvedProps = workInProgress.pendingProps;
const resolvedProps =
workInProgress.elementType === Component
? unresolvedProps
: resolveDefaultProps(Component, unresolvedProps);
// 更新组件
return updateClassComponent(
current,
workInProgress,
Component,
resolvedProps,
renderLanes,
);
}
// ...
}
}
current 是旧节点,workInProgress 是新节点,属于半成品,会在执行过程中一点点填充内容。
beginWork 会进行深度优先遍历,生成的新节点 workInProcess 会 tag 属性进入不同的 update 逻辑分支,比如常见的 updateHostRoot、updateClassComponent、updateFunctionComponent 等。
performUnitOfWork 中,调用完 beginWork 后,会返回一个 next。这个 next 就是下一个要处理的 fiber,是 unitOfWork 的子 fiber。
这个 next 会赋值给 workInProgress,然后 workLoopConcurrent 的循环会 处理这个新的 workInProcess。
但当 next 为 null,就表示找不到下一个 fiber 了,深度的 “递” 到底了,就要 调用 completeUnitOfWork,进行 “归” 的收尾工作。
completeUnitOfWork 做的主要工作有:
React 16 时会生成一个 effectList 来记录需要更新的节点,防止不必要的遍历整棵树。但 React 17 后被移除掉了,改成从 rootFiber 开始从上往下遍历。
调和阶段,主要分为 beginWork 和 completeUnitOfWork 两部分。
beginWork 自上而下,进行新旧节点对比,构造子 fiber,并打上 flag(插入、更新、删除),会执行 render(生成新 ReactElement) 之前的生命周期函数。对应以前 stack reconciler 架构中递归的 “递”。
completeUnitOfWork 自下而上,如果是插入,则构建真实 DOM 节点放到 fiber.stateNode 下,接着是处理 props,将属性添加到 DOM 上。
当前题目:理解 React 的调和器 Reconciler
文章来源:http://www.mswzjz.cn/qtweb/news16/39816.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能