|
1 | 1 | ## 原理
|
2 | 2 |
|
| 3 | +### 常规 DOM 渲染 |
3 | 4 |
|
| 5 | + |
| 6 | + |
| 7 | +我们知道目前所有的浏览器都是遵循类似上面图片所绘制出的工作流, 仅在细节处略有不同。 |
| 8 | + |
| 9 | +- 创建`DOM树` |
| 10 | + |
| 11 | + 一旦浏览器接收到一个`HTML`文件, 渲染引擎 `(render engine)` 就开始解析它, 并根据 HTML 元素 (elements)一一对应地生成`DOM节点 (nodes)`, 组成一棵`DOM树`。 |
| 12 | + |
| 13 | +- 创建渲染树 |
| 14 | + |
| 15 | + 同时, 浏览器也会解析来自外部`CSS文件`和元素上的`inline`样式。通常浏览器会为这些样式信息, 连同包含样式信息的`DOM树`上的节点, 再创建另外一个树, 一般被称作渲染树 `(render tree)` |
| 16 | + |
| 17 | +- 创建渲染树背后的故事 |
| 18 | + |
| 19 | + `WebKit`内核的浏览器上, 处理一个节点的样式的过程称为`attachment`。`DOM树`上的每个节点都有一个`attach`方法, 它接收计算好的样式信息, 返回一个`render`对象 (又名`renderer`) |
| 20 | + |
| 21 | + `Attachment` 的过程是同步的, 新节点插入 `DOM树`时, 会调用新节点的`attach`方法。 |
| 22 | + 构建渲染树时, 由于包含了这些 render 对象, 每个 render 对象都需要计算视觉属性 `(visual properties)`; 这个过程通过计算每个元素的样式属性来完成。 |
| 23 | + |
| 24 | +- 布局 `Layout` |
| 25 | + 又被简称为`Reflow` |
| 26 | + 构造了渲染树以后, 浏览器引擎开始着手布局 `(layout)`。布局时, 渲染树上的每个节点根据其在屏幕上应该出现的精确位置, 分配一组屏幕坐标值。 |
| 27 | +- 绘制 `Painting` |
| 28 | + |
| 29 | + 接着, 浏览器将会通过遍历渲染树, 调用每个节点的 `paint` 方法来绘制这些 `render` 对象。`paint` 方法根据浏览器平台, 使用不同的 `UI后端API` `(agnostic UI backend API)`。 通过绘制, 最终将在屏幕上展示内容。 |
| 30 | + |
| 31 | +`DOM操作` 真正的问题在于每次操作都会触发布局的改变、`DOM树` 的修改和渲染。`Virtual DOM`把管理 `DOM碎片`这件事情自动化、抽象化了, 使得你无需再去手动处理。 |
| 32 | + |
| 33 | +### 什么是 Virtual DOM? |
| 34 | + |
| 35 | +`Virtual DOM`是对`DOM`的抽象, 本质上是`JavaScript`对象, 这个对象就是更加轻量级的对`DOM`的描述. |
| 36 | + |
| 37 | +### 传统的 diff 算法 和 React 的 diff 算法 |
| 38 | + |
| 39 | +- 传统 `diff` 算法的复杂度为`O(n^3)` |
| 40 | + |
| 41 | +- `React diff`算法的复杂度为`O(n)` |
4 | 42 |
|
5 | 43 | ### 先序深度遍历
|
6 | 44 |
|
7 | 45 | - 先中后序遍历 -> 遍历根节点的顺序
|
8 | 46 |
|
9 |
| - - 先序 -> 根, 左, 右 |
| 47 | + - `先序 -> 根, 左, 右` |
10 | 48 |
|
11 |
| - - 中序 -> 左, 根, 右 |
| 49 | + - `中序 -> 左, 根, 右` |
12 | 50 |
|
13 |
| - - 后序 -> 左, 右, 根 |
| 51 | + - `后序 -> 左, 右, 根` |
14 | 52 |
|
15 | 53 | - 深度(DFS)遍历 -> 从根节点出发, 沿着左子树方向进行纵向遍历, 直到找到叶子节点为止。然后回溯到前一个节点, 进行右子树节点的遍历, 直到遍历完所有可达节点为止。
|
16 | 54 |
|
17 | 55 | - 广度(BFS)遍历 -> 从根节点出发, 在横向遍历二叉树层段节点的基础上纵向遍历二叉树的层次。
|
18 | 56 |
|
19 | 57 | 
|
20 | 58 |
|
| 59 | +### DOM Diff 算法策略 |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +### Mini Diff 算法实现 |
| 64 | + |
| 65 | +- 替换 |
| 66 | + - 节点替换 |
| 67 | + - 属性替换 |
| 68 | + - 文本替换 |
| 69 | + - 更多尚未实现 |
| 70 | + |
| 71 | +- 移除 |
| 72 | + - 节点移除 |
| 73 | + - 属性移除 |
| 74 | + - 文本移除 |
| 75 | + - 更多尚未实现 |
| 76 | + |
| 77 | +### Dom Diff 流程 |
| 78 | + |
| 79 | + |
| 80 | + |
21 | 81 | ## Demo
|
22 | 82 |
|
23 | 83 | [Link](https://rain120.github.io/vdom-diff-algorithm/)
|
|
48 | 108 |
|
49 | 109 | <<< @/src/vdom-diff/src/patch.ts
|
50 | 110 |
|
51 |
| -
|
52 | 111 | ## 参考
|
53 | 112 |
|
| 113 | +### Diff 相关 |
| 114 | +
|
| 115 | +[Diff Strategies](https://neil.fraser.name/writing/diff/) |
| 116 | +
|
54 | 117 | [React Diffing 算法](https://zh-hans.reactjs.org/docs/reconciliation.html#the-diffing-algorithm)
|
55 | 118 |
|
56 | 119 | [React's diff algorithm - Christopher Chedeau](https://calendar.perfplanet.com/2013/diff/)
|
57 | 120 |
|
58 | 121 | [React Dom Diff](https://sekaiamber.github.io/react-dom-diff/)
|
59 | 122 |
|
60 |
| -[virtual-dom](https://github.com/Matt-Esch/virtual-dom) |
| 123 | +[Under-the-hood-ReactJS](https://github.com/Bogdan-Lyashenko/Under-the-hood-ReactJS) |
| 124 | +
|
| 125 | +[babel-plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/) |
| 126 | +
|
| 127 | +[diff 算法原理概述](https://github.com/NervJS/nerv/issues/3) |
| 128 | +
|
| 129 | +[React 源码剖析系列 - 不可思议的 react diff](https://zhuanlan.zhihu.com/p/20346379) |
| 130 | +
|
| 131 | +### Virtual DOM 相关 |
| 132 | +
|
| 133 | +[snabbdom](https://github.com/snabbdom/snabbdom/blob/master/src/snabbdom.ts) |
61 | 134 |
|
62 | 135 | [How to write your own Virtual DOM](https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060)
|
63 | 136 |
|
64 |
| -[Under-the-hood-ReactJS](https://github.com/Bogdan-Lyashenko/Under-the-hood-ReactJS) |
| 137 | +[Mini Virtual DOM 实现](https://github.com/yelouafi/petit-dom) |
65 | 138 |
|
66 |
| -[babel-plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/) |
| 139 | +[virtual-dom](https://github.com/Matt-Esch/virtual-dom) |
| 140 | +
|
| 141 | +[解析 snabbdom 源码](https://github.com/creeperyang/blog/issues/33) |
| 142 | +
|
| 143 | +[为什么要使用 Virtual DOM](https://hashnode.com/post/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-cisczhfj41bmssp53mvfwmgrq) -> [中文版](https://www.zcfy.cc/article/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-hashnode-1211.html) |
| 144 | +
|
| 145 | +[浏览器的工作原理:新式网络浏览器幕后揭秘](https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/) |
0 commit comments