深度理解Virtual Dom
本质:维护状态更新视图
Virtual DOM 算法
DOM 树上的结构、属性信息我们都可以很容易地用 JavaScript 对象表示出来。
var olE = {
tagName: 'ol', // 标签名
props: { // 属性用对象存储键值对
id: 'ol-list'
},
children: [ // 子节点
{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
]
}
对应 HTML 写法是:
<ol id='ol-list'> <li class='item'>Item 1</li> <li class='item'>Item 2</li> <li class='item'>Item 3</li> </ol>
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文
档当中当状态变更时,重新构造一棵新的对象树。然后用新的树和旧的树进行比较两个数的差异。
然后把差异更新到久的树上,整个视图就更新了。Virtual DOM 本质就是在 JS 和 DOM 之间做
了一个缓存。既然已经知道 DOM 慢,就在 JS 和 DOM 之间加个缓存。JS 先操作 Virtual DOM
对比排序/变更,最后再把整个变更写入真实 DOM。
Virtual DOM实现
import * as el from 'Ele';
var ol = el('ol', {id: 'ol-list'}, [
el('li', {class: 'item'}, ['Item 1']),
el('li', {class: 'item'}, ['Item 2']),
el('li', {class: 'item'}, ['Item 3'])
]);
Ele.prototype.render = function () {
var e = document.createElement(this.tagName); // 创建元素
var props = this.props;
for (var propName in props) { // 设置 DOM 属性
var propValue = props[propName];
e.setAttribute(propName, propValue);
}
var children = this.children || [];
children.forEach(function (child) {
var childE = (child instanceof Element)
? child.render() // 子节点也是虚拟 DOM,递归构建
: document.createTextNode(child); // 字符串,构建文本节点
e.appendChild(childE);
});
return e;
}
最后只需要 render。
var olE = Ele.render() document.body.appendChild(olE);
上面的 olE 是真正的 DOM 节点,把它 append 到 body 中,这样就有了真正的 ol DOM 元素。
Virtual DOM 树的差异介绍(Diff算法)
比较两个 DOM 树的差异是 Virtual DOM 算法最核心的部分,这也是所谓的 Virtual DOM 的
diff 算法。在前端当中,很少会跨越层级地移动 DOM 元素。所以 Virtual DOM 只会对同一个
层级的元素进行对比,下面的 div 只会和同一层级的 div 对比,第二层级的只会跟第二层级对
比。采用的是深度优先遍历,来记录差异,这样每个节点都会有一个唯一的标记。

差异是指的是什么呢?DOM 替换掉原来的节点,如把上面的 div 换成了 section 进行移动、删
除、新增子节点,例如上面 div 的子节点,把 p 和 span 顺序互换修改了节点的属性。对于文本
节点,文本内容可能会改变。
如果我把左侧的 p、span、div 反过来变成 div、p、span 怎么办?按照差异正常会被替换掉,
但这样 DOM开销就会异常的大了。而 React 帮我们做到不需要替换节点,而只需要经过节点移
动就可以达到。
参考链接 ,转载自:https://www.cnblogs.com/wubaiqing/p/6726429.html

浙公网安备 33010602011771号