Skip to content

Commit b209033

Browse files
committed
feat(commitRoot): 新增 commitRoot 源码注释
1 parent adcc701 commit b209033

File tree

9 files changed

+317
-193
lines changed

9 files changed

+317
-193
lines changed

README-ME.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,17 +474,66 @@ export function updateContainer(
474474
react 为不同的更新划分了不同的层级
475475
一共有 31 个 层级,源码中是使用 二进制来表示, 源码位置在 `ReactFiberLane.old.js`
476476
477-
也可以在 [在线源码](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberLane.old.js#L31) 中查看
477+
也可以在 [在线源码](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberLane.old.js#L31) 中查看
478478
479479
## 创建虚拟 dom
480480
481-
在 react 中 创建 虚拟 dom,是从 `workLoopConcurrent()` 方法开始到 `performUnitOfWork` 递归调用 `beginWork` 进行创建 虚拟 dom,也就是 fiber,该部分源码可以在 [这里体现](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L1558)
481+
在 react 中 创建 虚拟 dom,是从 `workLoopConcurrent()` 方法开始到 `performUnitOfWork` 递归调用 `beginWork` 进行创建 虚拟 dom,也就是 fiber,该部分源码可以在 [这里体现](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L1558)
482482
483483
### beginWork
484+
`beginWork(current, workInProgress, renderLanes)`
484485
485-
在页面初次渲染的时候,会递归创建 `fiber` 节点,从 `beginWork` 会从根节点开始采用深度遍历的方式,递归创建子 `fiber` 节点,`beginWork` 的源码在 [这里体现](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberBeginWork.old.js#L3188),
486+
487+
488+
在页面初次渲染的时候,会递归创建 `fiber` 节点,从 `beginWork` 会从根节点开始采用深度遍历的方式,递归创建子 `fiber` 节点,`beginWork` 的源码在 [这里体现](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberBeginWork.old.js#L3188),
486489
487490
添加了注释的源代码在 [这里](https://github.com/coderlfm/react/blob/feature/src/react/v17.0.2/react-reconciler/src/ReactFiberBeginWork.old.js)
488491
489492
### 创建真实 dom
490-
在 beginWork 递归到底之后,开始从底部开始递归到顶创建真实 `dom`,
493+
在 beginWork 递归到底之后,开始从底部开始递归到顶创建真实 `dom`,
494+
<br><br>
495+
496+
497+
## commitRoot
498+
在创建完 `虚拟dom``真实dom` 的时候,最终需要进行 `commit` 具体源码体现在 [这里](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L1038)
499+
500+
而在 commit 中,最主要有三个函数
501+
- [commitBeforeMutationEffects](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L2026)
502+
- [commitMutationEffects](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L2063)
503+
- [commitLayoutEffects](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L2098)
504+
505+
> 这三部分在 17.0.2 中是在 do while 循环中调用,但是在下一个版本中有修改
506+
每个阶段都有对应的 `begin` `complete` `OnFiber` 方法
507+
508+
<br><br>
509+
510+
### `commitBeforeMutationEffects` mutation 前
511+
512+
在该方法中的 `commitBeforeMutationEffects_begin` 会先执行 删除的操作
513+
这一步会执行 派发 `beforeblur` 元素失去焦点事件
514+
515+
`commitBeforeMutationEffectsOnFiber` 会判断fiber 节点的类型,其中需要主要两种类型, `ClassComponent``HostRoot`(根组件)
516+
- `ClassComponent` 会在这个阶段调用 [`getSnapshotBeforeUpdate()`](https://github.com/facebook/react/blob/e0d9b289998c66d2e4fb75582b9e107054e4e0a4/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L486)
517+
- `HostRoot` 会在这个阶段 [清空真实dom中的内容](https://github.com/facebook/react/blob/e0d9b289998c66d2e4fb75582b9e107054e4e0a4/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L510)
518+
<br><br>
519+
520+
### `commitMutationEffects` mutation 中
521+
522+
在该方法中的 `commitMutationEffects_begin` 会先执行 删除的操作
523+
`commitDeletion` 该方法中会调用 `unmountHostComponents` 从父节点向下递归,如果是根节点接着调用 `commitNestedUnmounts` 然后 `while` 循环调用 `commitUnmount`来递归调用子组件的销毁函数,
524+
- 函数式组件,会在这一步调用 `useeffect` 的[销毁函数](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L1226)
525+
- 类组件,会在这一步调用 类组件的 [componentWillUnmount](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L1242) 生命周期函数
526+
527+
528+
`commitMutationEffectsOnFiber` 中会判断effect 的类型 其中有 placement | updates | PlacementAndUpdate 等
529+
- [commitPlacement](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L1541) 新增 取到当前 元素的父节点,以及当前元素的兄弟节点,如果有兄弟节点就使用 `insertInContainerBefore` 否则使用 `appendChildToContainer`
530+
- [Update](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L2274) 更新 判断当前 fiber 的tag,如果是函数式组件,先调用 [commitHookEffectListUnmount](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L1816) 执行 useeffect 的 卸载函数
531+
如果是 原生 dom元素,则更新该dom身上的属性
532+
<br><br>
533+
534+
### `commitLayoutEffects` mutation
535+
在该方法中的 `commitLayoutMountEffects_complete` 中会判断effect 的类型,其中需要注意的是函数式组件和类组件
536+
- [函数式组件]() 先调用 [safelyCallCommitHookLayoutEffectListMount](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L2416) 然后调用 [commitHookEffectListMount](https://github.com/facebook/react/blob/e0d9b289998c66d2e4fb75582b9e107054e4e0a4/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L568) 在 `commitHookEffectListMount` 中 使用 `do while` 循环 **执行了 所有effect链表中的 副作用函数** 并且 **记录了 所有effect链表中的 销毁函数**
537+
- [类组件]() 先调用 [safelyCallComponentDidMount](https://github.com/facebook/react/blob/e0d9b289998c66d2e4fb75582b9e107054e4e0a4/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L2423) 然后调用 类组件的 [`componentDidMount`](https://github.com/facebook/react/blob/e0d9b289998c66d2e4fb75582b9e107054e4e0a4/packages/react-reconciler/src/ReactFiberCommitWork.old.js#L253) 生命周期函数
538+
539+
## diff 算法

src/App.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import State from './components/State'
33
import LanesDemo from './components/LanesDemo'
44
import AppSibling from './components/AppSibling'
@@ -20,17 +20,31 @@ import './App.css';
2020
}*/
2121
function App() {
2222

23+
useEffect(() => {
24+
console.log('useEffect被执行');
25+
return () => {
26+
console.log('useEffect 卸载函数被执行');
27+
}
28+
}, [])
29+
30+
const [conut, setCount] = useState(1)
31+
2332
// 事件系统
2433
// return <EventDemo/>
2534

2635
// return <Hooks/>
2736
// fiber树
28-
// return (
29-
// <div className="App">
30-
// <span className={'app-span'} onClick={() => setCount(count + 1)}>App{count}</span>
31-
// <AppSibling count={count}/>
32-
// </div>
33-
// );
37+
return (
38+
<div className="App">
39+
<span onClick={() => {
40+
debugger
41+
setCount(conut + 1);
42+
}}>我是span {conut}</span>
43+
<h2>我是h2</h2>
44+
</div>
45+
);
46+
{/* <span className={'app-span'} onClick={() => setCount(count + 1)}>App{count}</span> */ }
47+
{/* <AppSibling count={count}/> */ }
3448

3549
// Scheduler调度任务与用户交互
3650
// return <SchedulerTask/>
@@ -39,7 +53,7 @@ function App() {
3953
// return <TasksWithDifferentPriorities/>
4054

4155
// context
42-
return <ContextDemo/>
56+
// return <ContextDemo/>
4357

4458
// diff 算法
4559
// return <Diff ref={'diffRef'}/>

src/react/v17.0.2/react-dom/src/client/ReactDOMComponent.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,22 +338,24 @@ function setInitialDOMProperties(
338338
}
339339
}
340340

341+
// 将props上的属性设置到dom身上
341342
function updateDOMProperties(
342343
domElement: Element,
343344
updatePayload: Array<any>,
344345
wasCustomComponentTag: boolean,
345346
isCustomComponentTag: boolean,
346347
): void {
347348
// TODO: Handle wasCustomComponentTag
349+
// 在 updatPayload 中数组的第[i] 项是更新的key,第 [i+1]项 是更新的值,
348350
for (let i = 0; i < updatePayload.length; i += 2) {
349351
const propKey = updatePayload[i];
350352
const propValue = updatePayload[i + 1];
351353
if (propKey === STYLE) {
352-
setValueForStyles(domElement, propValue);
354+
setValueForStyles(domElement, propValue); // 设置样式
353355
} else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
354356
setInnerHTML(domElement, propValue);
355357
} else if (propKey === CHILDREN) {
356-
setTextContent(domElement, propValue);
358+
setTextContent(domElement, propValue); // 设置文本属性
357359
} else {
358360
setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
359361
}

src/react/v17.0.2/react-dom/src/client/ReactDOMHostConfig.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ export function commitMount(
450450
}
451451
}
452452

453+
// 更新元素
453454
export function commitUpdate(
454455
domElement: Instance,
455456
updatePayload: Array<mixed>,
@@ -484,6 +485,7 @@ export function appendChild(
484485
parentInstance.appendChild(child);
485486
}
486487

488+
// 将 内容插入到父容器中
487489
export function appendChildToContainer(
488490
container: Container,
489491
child: Instance | TextInstance,
@@ -674,6 +676,7 @@ export function unhideTextInstance(
674676

675677
export function clearContainer(container: Container): void {
676678
if (container.nodeType === ELEMENT_NODE) {
679+
// 先将元素清空
677680
((container: any): Element).textContent = '';
678681
} else if (container.nodeType === DOCUMENT_NODE) {
679682
const body = ((container: any): Document).body;

0 commit comments

Comments
 (0)