[H5]DOM和Virtual DOM之间的区别

DOM

  • DOM代表了Document Object Model
  • DOM是一种抽象化的结构性文本
  • DOM的作用只是需要能够直接获取东西
    对于Web Developers来说,这种结构性的文本就是HTML code,并且 DOM被简单的称为HTML DOM。HTML code中的elements就变成了DOM中的nodes

所以,既然HTML是一种文本,那么DOM就是HTML在内存中的表现形式。

将它与程序的一个实例进行比较。你可以在同一个程序的多个过程,就像你可以有多个相同的HTML DOM(例如同一页面加载多标签)。

HTML DOM提供了能够过去和修改Node的API,例如:getElementByIdremoveChild
我们通常使用JavaScript来操作DOM对象。

下面举个栗子:

var item = document.getElementById("hei");
item.parentNode.removeChild(item);

document对象是HTML DOM中root node的一个抽象体。

遇到的问题

由于HTML文档的结构允许,所以HTML DOM使用的是树结构。这就很厉害了,因为通过树结构我们可以很容易地遍历树。不幸的是,很容易操作并不意味着很快
现在的WEB程序中,DOM树�非常巨大。因为我们越来越推向动态Web应用程序(Single Page Applications - SPAs),我们需要大量的不断的修改DOM树。�这真的非常痛苦。
顺便说一下,假如我自己设法创造一个5GB +源网页。它其实不是很难。但是考虑一下,我们将要在DOM使成千上万的div。记住,我们是现代的程序猿,我们写出的代码应该很容易管理!我们的方法,处理事件-点击提交,很多,型INS…
比方说,典型的jQuery事件处理程序看起来像这一样:
1、查找对事件感兴趣的每一个节点
2、必要时更新
其中有两个问题:

  • 很难管理。
    想象一下,你必须调整一个事件处理程序。如果你失去了背景,你必须潜水真正深入到代码,甚至知道发生了什么事。

  • 耗时和错误风险。
    它的效率很低。我们真的需要手动做所有这些调查结果吗?也许我们可以更聪明,并提前告诉哪些节点是要更新?

那么Virtual DOM则是为了解决以上这些问题。

Virtual DOM

首先需要讲明的一点Virtual DOM技术并不是React发明的,但是React确实是使他发扬光大的。

Virtual DOM是HTML DOM的抽象。它是轻量级和脱离浏览器的具体实施细节。因为DOM本身已经是一个抽象的、虚拟的DOM,事实上,Virtual DOM是一个抽象的抽象。

实际上,Virtual DOM包含:

  • Javascript DOM模型树(VTree),类似文档节点树(DOM)
  • DOM模型树转节点树方法(VTree -> DOM)
  • 两个DOM模型树的差异算法(diff(VTree, VTree) -> PatchObject)
  • 根据差异操作节点方法(patch(DOMNode, PatchObject) -> DOMNode)

VTree

VTree模型非常简单,基本结构如下:

{ 
  // tag的名字 
  tagName: 'p', 
  // 节点包含属性 
  properties: { style: { color: '#fff' } }, 
  // 子节点 
  children: [], 
  // 该节点的唯一表示,后面会讲有啥用
  key: 1
}

所以我们很容易写一个方法来创建这种树状结构,例如React是这么创建的:

// 创建一个divreact.createElement('div', null, [ 
  // 子节点img 
  react.createElement('img', { src: "avatar.png", class: "profile" }), 
  // 子节点h3 
  react.createElement('h3', null, [[user.firstName, user.lastName].join(' ')])
]);

VTree -> DOM

这方法也不太难,我们实现一个简单的:

function create(vds, parent) { 
  // 首先看看是不是数组,如果不是数组统一成数组 
  !Array.isArray(vds) && (vds = [vds]); 
  // 如果没有父元素则创建个fragment来当父元素 
  parent = parent || document.createDocumentFragment(); var node; 
  // 遍历所有VNode 
  vds.forEach(function (vd) { 
      // 如果VNode是文字节点 
      if (isText(vd)) { 
        // 创建文字节点 
        node = document.createTextNode(vd.text); 
        // 否则是元素
      } else { 
        // 创建元素 
        node = document.createElement(vd.tag); 
      } 
      // 将元素塞入父容器 
      parent.appendChild(node); 
      // 看看有没有子VNode,有孩子则处理孩子
      VNode vd.children && vd.children.length && create(vd.children, node); 
      // 看看有没有属性,有则处理属性 
      vd.properties && setProps({ style: {} }, vd.properties, node); }); 
      return parent;}

diff(VTree, VTree) -> PatchObject

差异算法是Virtual DOM的核心,实际上该差异算法是个取巧算法(当然你不能指望用O(n^3)的复杂度来解决两个树的差异问题吧),不过能解决Web的大部分问题。
那么React是如何取巧的呢?

  • 分层对比

如图,React仅仅对同一层的节点尝试匹配,因为实际上,Web中不太可能把一个Component在不同层中移动。

  • 基于key来匹配
    还记得之前在VTree中的属性有一个叫key的东东么?这个是一个VNode的唯一识别,用于对两个不同的VTree中的VNode做匹配的。



    这也很好理解,因为我们经常会在Web遇到拥有唯一识别的Component(例如课程卡片、用户卡片等等)的不同排列问题。

  • 基于自定义元素做优化
    React提供自定义元素,所以匹配更加简单。


patch(DOMNode, PatchObject) -> DOMNode

由于diff操作已经找出两个VTree不同的地方,只要根据计算出来的结果,我们就可以对DOM的进行差异渲染。

总结:

  • 给定一个可以代表DOM结构的VTree结构
  • 通过vdom/create-element函数来创建DOM中的节点
  • 通过将vdom/patch函数将vtree/diff函数根据两个不同的vtree结构产生的patch包,更新的DOM中

引用

前沿技术揭秘
The difference between Virtual DOM and DOM

扩展阅读

Matt-Esch/virtual-dom

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容