菜单

一道了解 Virtual DOM

2018年11月16日 - JavaScript

一道了解 Virtual DOM

2016/11/14 · JavaScript
· DOM

正文作者: 伯乐在线 –
luobotang
。未经作者许可,禁止转载!
接加入伯乐在线 专辑作者。

前言

React 好像早就火了生长远很长远,以致被我们对此 Virtual DOM
这个词都已经死熟稔了,网上为生大多之牵线 React、Virtual DOM
的章。但是直到日前自特别花工夫错开学学 Virtual DOM,才受我对 Virtual
DOM
有了必然之理解,以致吃要怀疑起大悠久之前看罢之那些文章来。倒不是这些文章称得反常,而是现在于自己看来角度不太好,说得越来越多,越说不清。

深受自己力所能及享有开窍(自认为)的,是当下篇文章:


Change And Its Detection In JavaScript Frameworks
Monday Mar 2, 2015 by Tero Parviainen
http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html


笔者看题目的角度大过硬,从数变动和UI同步的角度来介绍各个典型框架,特别是对此
React 的 Virtual DOM,从夫角度理解起来再易把。

感谢兴趣之同班,如果没读了就首文章,推荐去押无异押,不感兴趣就算是了。不过接下去自己一旦提的物,部分整理起即首文章,特别是从立篇稿子中引用的图形,非常棒。当然还有本人好之有想,以及一些对当前
Virtual DOM 实现的开源库的剖析。

万一念了面推荐的即首文章,我倒不在意你不再接续将本文读下去,因为微微东西你曾经领会到了。当然,也无反对。

前言

React 好像都火了那个漫长很长远,以致于我们对于 Virtual DOM
这个词都已经充分熟稔了,网上为发好多之牵线 React、Virtual DOM
的稿子。但是直至日前自己特意花工夫错开读书 Virtual DOM,才叫自身对 Virtual
DOM
有了肯定之敞亮,以致被要怀疑起杀悠久之前看了之那些文章来。倒不是这些文章说得反常,而是现在以自家看来角度不顶好,说得越来越多,越说不清。

吃自身能拥有开窍(自当)的,是即刻篇稿子:


Change And Its Detection In JavaScript Frameworks
Monday Mar 2, 2015 by Tero Parviainen
http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html


笔者看题目的角度大棒,从数据变动和UI同步的角度来介绍各个典型框架,特别是对
React 的 Virtual DOM,从夫角度理解起来重便于把。

谢兴趣的校友,如果无读了这首文章,推荐去看同样扣押,不感兴趣就到底了。不过接下去自己只要摆的事物,部分整理起即篇文章,特别是自即首稿子中援的图,非常棒。当然还有自己要好的一对琢磨,以及有对此当下
Virtual DOM 实现的开源库的分析。

若是念了端推荐的这篇稿子,我倒不介意你不再接续将本文读下来,因为有点东西你曾领会到了。当然,也未反对。

扭转就宗事

议论页面的浮动前,咱们先看下多少及页面(视觉层面的页面)的涉及。数据是东躲西藏在页面下,通过渲染展示让用户。同样的数目,按照不同之页面设计以及贯彻,会坐不同款式、样式的页面呈现出来。有时候在一个页面内的例外岗位,也会发生同一数量的不同表现。

Paste_Image.png

Web
的初,这些页面通常是静态的,页面内容未会见扭转。而如果数量发生了转移,通常需再行请页面,得到基于新的数据渲染出的初的页面。

Paste_Image.png

最少,这个模式了解起来特别简单不是啊。

以至 Web
应用复杂起来,开发者们开始关心用户体验,开始拿大气底处理为前者迁移,页面变得动态、灵活起来。一个鲜明的风味是,数据发生变化之后,不再用刷新页面就可知来看页面及之始末就更新了。

前者需要举行的业务变得多矣起,前端工程师等为不怕修炼了四起,各种前端技术吧就涌出了。

首先,聪明的工程师等发现既然是于前端渲染页面,如果光是一些数额来了变动,就假设把页面整体还是同等挺块区域还渲染就闹硌痴了。为什么不将事情做得又极端致些,只更新变更的数额对应之页面的情节也?

岂开吗?操作 DOM 呗。DOM
就是浏览器提供于开发者用于操作页面的型嘛,直接通过下面本来调用 DOM
的各种接口就 OK 了。而且我们尚出矣诸如 jQuery 这样的棒棒的工具,操作 DOM
变得 so easy。

然,页面越来越复杂,聪明的工程师们发现数目变动后,老是用手动编码去操作对应的
DOM
节点执行更新,有接触烦,不够懒啊。于是各种框架而恒河沙数一般冒出了,纷纷表示可以简化这进程。

小早期的框架来这般的:

Paste_Image.png

开发者借助框架,监听数据的改,在数额变动后更新对应的 DOM
节点。虽然还是如写一些代码,但是写出来的代码好像特别有系统的旗帜,至少还易懂以及护卫了,也不易嘛。

还进一步,MVVM 框架出现了,以 AngularJS 为代表:

Paste_Image.png

还是数变动后更新对应 DOM
节点的方式,但是建立这种绑定关系之过程让框架所拍卖,开发者要描绘的代码变少了,而且代码更易于读与保护了。

再然后呢,大家便当这棒棒的模式及继承深耕,纷纷表示还得在性能上召开得重新好,前端领域同样切片繁荣。

再次后来 React 出现了,它不仅不是 MVVM 框架,甚至并 MV*
框架还无是。这年头,不是个 MV* 框架还好意思出门?可 React
还当真带来了新的笔触!

哟思路也?

尽管回去过去,回到生简单而美好的下。具体而言,就是历次数据发生变化,就更履行同一糟糕完整渲染。的确这样再简便易行,不用去雕饰到底是数量的啊部分别了,需要创新页面的哪一部分。但是坏处太明确,体验不好什么。而
React 给闹了化解方案,就是 Virtual DOM。

Virtual DOM 概况来讲,就是于数额与真 DOM
之间成立了千篇一律层缓冲。对于开发者而言,数据变动了不畏调用 React
的渲染方法,而 React 并无是一直得到新的 DOM 进行调换,而是先生化作 Virtual
DOM,与达一样不行渲染得到的 Virtual DOM 进行比对,在渲染得到的 Virtual DOM
上发现变化,然后拿变的地方更新至真 DOM 上。

简短来说,React 在提供于开发者简单的开发模式之情状下,借助 Virtual DOM
实现了性能达到的优化,以致吃敢说自己“不慢”。

变迁及时桩事

议论页面的转变前,咱们先押下数据和页面(视觉层面的页面)的涉。数据是隐身在页面下,通过渲染展示受用户。同样的数量,按照不同的页面设计与促成,会因不同式样、样式的页面呈现出来。有时候在一个页面内的两样职位,也会见时有发生雷同数量的不比表现。

图片 1

Paste_Image.png

Web
的首,这些页面通常是静态的,页面内容不会见转变。而一旦数额来了别,通常用重请页面,得到基于新的数额渲染出之初的页面。

图片 2

Paste_Image.png

起码,这个模式了解起来老简单不是也。

直至 Web
应用复杂起来,开发者们开关注用户体验,开始以大量底拍卖为前者迁移,页面变得动态、灵活起来。一个斐然的性状是,数据发生变化之后,不再用刷新页面就能够观看页面及之情节就更新了。

前者需要举行的事务变得差不多了起,前端工程师等也就修炼了起来,各种前端技术为便起了。

率先,聪明的工程师们发现既然是以前者渲染页面,如果只是局部多少发生了变更,就如将页面整体还是同一不行块区域还渲染就生出接触痴了。为什么非把工作做得重极致致些,只更新变更之数对应的页面的情吗?

岂开啊?操作 DOM 呗。DOM
就是浏览器提供于开发者用于操作页面的范嘛,直接通过下本来调用 DOM
的各种接口就 OK 了。而且我们还发了如 jQuery 这样的棒棒的家伙,操作 DOM
变得 so easy。

然而,页面越来越复杂,聪明之工程师等发现数变化后,老是用手动编码去操作对应之
DOM
节点执行更新,有硌烦,不够懒啊。于是各种框架而雨后春笋一般出现了,纷纷表示可以简化这进程。

微早期的框架来这样的:

图片 3

Paste_Image.png

开发者借助框架,监听数据的改动,在数量变动后更新对应之 DOM
节点。虽然要要描绘有代码,但是写出来的代码好像很有系统的规范,至少再爱懂与维护了,也无可非议嘛。

再进一步,MVVM 框架出现了,以 AngularJS 为表示:

图片 4

Paste_Image.png

依然是多少变化后更新对应 DOM
节点的法门,但是建立这种绑定关系的进程让框架所处理,开发者要描绘的代码变少了,而且代码更易读与保安了。

再然后呢,大家便以这棒棒的模式上继续深耕,纷纷表示还好于性能上召开得重复好,前端领域同样切开繁荣。

还后来 React 出现了,它不光未是 MVVM 框架,甚至连 MV
框架都未是。这年头,不是单 MV 框架还好意思出门?可 React
还真带来了初的笔触!

好家伙思路为?

哪怕回去过去,回到那个简单而美好的时段。具体而言,就是历次数据发生变化,就再履行同样次完整渲染。的确如此又简短,不用失去琢磨到底是数额的哇部分变动了,需要更新页面的呀一部分。但是坏处太强烈,体验不好什么。而
React 给闹了化解方案,就是 Virtual DOM。

Virtual DOM 概况来讲,就是当数量及诚 DOM
之间成立了平等重合缓冲。对于开发者而言,数据变化了即调用 React
的渲染方法,而 React 并无是一直获得新的 DOM 进行调换,而是先生化作 Virtual
DOM,与达同坏渲染得到的 Virtual DOM 进行比对,在渲染得到的 Virtual DOM
上发现变化,然后将转变之地方更新到实际 DOM 上。

简言之的话,React 在供于开发者简单的开模式的事态下,借助 Virtual DOM
实现了性达到之优化,以致吃敢说好“不慢”。

Virtual DOM

React 基于 Virtual DOM 的数码更新和UI同步机制:

React – 初始渲染

起来渲染时,首先将数据渲染为 Virtual DOM,然后由 Virtual DOM 生成 DOM。

React – 数据更新

数码更新时,渲染得到新的 Virtual DOM,与齐一致差拿走的 Virtual DOM 进行
diff,得到有需要在 DOM 上进行的转移,然后以 patch 过程遭到利用到 DOM
上实现UI的一头创新。

Virtual DOM 作为数据结构,需要能纯粹地变为真正
DOM,并且有利于开展对照。除了 Virtual DOM 外,React
还实现了别样的特点,为了专注让 Virtual DOM,我另外找了一定量只比较 Virtual
DOM 来读书:

此处也引进给谢兴趣都还不曾读了少单库源码的同学。

鉴于单独关注 Virtual DOM,通过阅读两个仓库的源码,对于 Virtual DOM
的稳出矣又充分一步的明亮。

第一看数据结构。

** Virtual DOM 数据结构 **

DOM 通常被视为等同棵树,元素虽然是及时株树上的节点(node),而 Virtual DOM
的底子,就是 Virtual Node 了。

当 virtual-dom 中,给 Virtual Node 声明了相应的类
VirtualNode,基本是用于存储数据,包括:

Snabbdom 的 Virtual Node 则是彻头彻尾数据对象,通过
vnode
模片来创造,对象属性包括:

则拥有差别,除去实现上的歧异和储藏室本身的附加特性,可以看来 Virtual Node
用于创造真实节点的数额包括:

发生矣这些其实就是得创建对应的真节点了。

创建 Virtual DOM

嵌套 Virtual Node 就可以获平等蔸树了。virtual-dom 和 Snabbdom
都提供了函数调用的艺术来创造 Virtual Tree,这个过程即是渲染了:

var vTree = h('div', [
  h('span', 'hello'),
  h('span', 'world')
])

React 提供 JSX 这粒糖,使得我们得为此接近 HTML
的语法来编排,不过编译后精神还是经过函数调用来获取相同蔸嵌套的 Virtual
Tree。而且这对了解 Virtual DOM 机制以来不是特地重大,先凭这。

使用 Virtual DOM

首先来拘禁初始化,virtual-dom 提供了
createElement
函数:

var rootNode = createElement(tree)
document.body.appendChild(rootNode)

冲 Virtual Node 创建真实 DOM 元素,然后再次长至页面及。

再来拘禁更新。virtual-dom 有显著的两步操作,首先 diff,然后 patch:

var newTree = render(count)
var patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)

比方 Snabbdom 则略些,只来一个 patch
函数,内部以展开比对的以以创新应用至了真 DOM 上,而且初始化也是因此底
patch 函数:

var vnode = render(data)
var container = document.getElementById('container')
patch(container, vnode)

// after data changed
var newVnode = render(data)
patch(vnode, newVnode)

属性优化

至于性优化,除了 Virtual DOM 机制自我提供的特色外,再不怕不同之
Virtual DOM 库自身的优化方案了,这个好看上面两个仓库底文档,不再赘言。

骨子里提到 Virtual DOM
的别比对,有人会指向那个内部如何处理数组感兴趣。的确,如果反复组元素的职务有了转移,这个要辨识起来是发接触麻烦。为这个,上面两单仓库与
React 其实都于 Virtual Node
上格外记录了一个性能“key”,就是之所以来扶持进行 Virtual Node 的比对的。

简而言之来说,如果个别单 Virtual Node 的职务不同,但是 key
属性相同,那么会用随即片独节点视为由同数量渲染得到的,然后一发开展差别分析。所以,并无是单以岗位展开比对,具体的贯彻好查各个库房的源码。

Virtual DOM

React 基于 Virtual DOM 的数额更新和UI同步机制:

图片 5

React – 初始渲染

始发渲染时,首先用数据渲染为 Virtual DOM,然后由 Virtual DOM 生成 DOM。

图片 6

React – 数据更新

数据更新时,渲染得到新的 Virtual DOM,与上等同坏获得的 Virtual DOM 进行
diff,得到有需要以 DOM 上进行的转,然后于 patch 过程中运用至 DOM
上落实UI的一块儿创新。

Virtual DOM 作为数据结构,需要会规范地换为实际
DOM,并且有利于进行比。除了 Virtual DOM 外,React
还落实了任何的特性,为了专注让 Virtual DOM,我另外找了少数只比 Virtual
DOM 来上学:

此间也推荐给谢兴趣还还尚未读了些微只库源码的同窗。

是因为只有关注 Virtual DOM,通过翻阅两单仓库底源码,对于 Virtual DOM
的定点来了还要命一步之明。

先是看数据结构。

Virtual DOM 数据结构

DOM 通常给视为等同株树,元素虽然是就株树上的节点(node),而 Virtual DOM
的基本功,就是 Virtual Node 了。

在 virtual-dom 中,给 Virtual Node 声明了对应的类
VirtualNode,基本是用于存储数据,包括:

Snabbdom 的 Virtual Node 则是彻头彻尾数据对象,通过
vnode
模片来创造,对象属性包括:

则具有差距,除去实现上的差别和仓库本身的附加特性,可以视 Virtual Node
用于创造真实节点的数据包括:

来矣这些实际就是足以创建对应的真正节点了。

创建 Virtual DOM

嵌套 Virtual Node 就可博同蔸树了。virtual-dom 和 Snabbdom
都提供了函数调用的章程来创造 Virtual Tree,这个过程就是是渲染了:

JavaScript

var vTree = h(‘div’, [ h(‘span’, ‘hello’), h(‘span’, ‘world’) ])

1
2
3
4
var vTree = h(‘div’, [
  h(‘span’, ‘hello’),
  h(‘span’, ‘world’)
])

React 提供 JSX 这粒糖,使得我们得以用接近 HTML
的语法来编排,不过编译后精神还是通过函数调用来抱一致蔸嵌套的 Virtual
Tree。而且这对了解 Virtual DOM 机制以来不是特意重大,先凭这。

使用 Virtual DOM

第一来拘禁初始化,virtual-dom 提供了
createElement
函数:

JavaScript

var rootNode = createElement(tree) document.body.appendChild(rootNode)

1
2
var rootNode = createElement(tree)
document.body.appendChild(rootNode)

冲 Virtual Node 创建真实 DOM 元素,然后重新添至页面及。

再度来拘禁更新。virtual-dom 有强烈的两步操作,首先 diff,然后 patch:

JavaScript

var newTree = render(count) var patches = diff(tree, newTree) rootNode =
patch(rootNode, patches)

1
2
3
var newTree = render(count)
var patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)

一旦 Snabbdom 则略些,只生一个 patch
函数,内部在开展比对的以用创新应用及了真格 DOM 上,而且初始化也是为此之
patch 函数:

JavaScript

var vnode = render(data) var container =
document.getElementById(‘container’) patch(container, vnode) // after
data changed var newVnode = render(data) patch(vnode, newVnode)

1
2
3
4
5
6
7
var vnode = render(data)
var container = document.getElementById(‘container’)
patch(container, vnode)
 
// after data changed
var newVnode = render(data)
patch(vnode, newVnode)

特性优化

有关性优化,除了 Virtual DOM 机制自我提供的特征外,再不怕不同之
Virtual DOM 库自身的优化方案了,这个好看上面两个仓库底文档,不再赘言。

实在提到 Virtual DOM
的差距比对,有人会对那个里面如何处理数组感兴趣。的确,如果频繁组元素的位置有了变动,这个要辨别起来是发生接触麻烦。为者,上面两独仓库以及
React 其实都以 Virtual Node
上格外记录了一个特性“key”,就是之所以来支援进行 Virtual Node 的比对的。

简来说,如果少独 Virtual Node 的职不同,但是 key
属性相同,那么会将立即点儿单节点视为由同数量渲染得到的,然后一发进展差别分析。所以,并无是只以岗位展开比对,具体的实现好查阅各个库房底源码。

小结

OK,以上就是是自若谈的总体持有情节了。

深信不疑广大同学之前对 Virtual DOM
已经生熟稔了,比自己清楚得又深切之同班相信呢非会见少。不过自从“数据变化及UI同步创新”这个角度来了解
Virtual DOM,在我看来是比好的,所以整在这边了。

发出个问题大常见,AngularJS 和 React 哪个更好?

如若说各级出千秋的讲话,估计大家就是“呵呵”了。但是就半独框架/库从“数据变动以及UI同步创新”的角度来拘禁,的确还解决了问题,而且缓解问题的方式大家还深认可(至少在欣赏她的同学眼里是这样的)。

并且,如果大家关注 Vue 的语,可以看,这个 MVVM 框架已经颁布了
2.0,其中便下了 Virtual DOM 实现其UI同步创新!所以,这的确不矛盾啊。

次只又,技术本身不是目的,能够再度好地解决问题才是王道嘛。

小结

OK,以上就是是自个儿只要摆的方方面面备内容了。

信任广大同桌之前对 Virtual DOM
已经不行熟悉了,比自己晓得得重新透之同校相信吗不见面丢掉。不过由“数据变动与UI同步创新”这个角度来解
Virtual DOM,在我看来是较好之,所以整在此间了。

起个问题很常见,AngularJS 和 React 哪个更好?

若说每起千秋的说话,估计大家便“呵呵”了。但是及时简单单框架/库从“数据变动与UI同步更新”的角度来拘禁,的确都解决了问题,而且解决问题的方大家都生认可(至少在喜欢它的校友眼里是这般的)。

又,如果大家关心 Vue 的语句,可以看看,这个 MVVM 框架都宣告了
2.0,其中即使用了 Virtual DOM 实现该UI同步创新!所以,这确实不矛盾啊。

亚单又,技术本身不是目的,能够再好地解决问题才是王道嘛。

打赏支持我形容有又多好文章,谢谢!

打赏作者

打赏支持自己写有重新多好文章,谢谢!

任选一栽出办法

图片 7
图片 8

1 赞 3 收藏
评论

关于作者:luobotang

图片 9

前端工程师@网易
个人主页 ·
我的篇章 ·
4 ·
 

图片 10

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图