关于Virtual Dom的那些事(一)

前言

一直想写点关于Virtual Dom的东西。以前刚开始接触react的时候就已经接触到了Virtual Dom和diff算法的概念,但一直觉得这些都是很复杂,很高深的东西。后面使用react,使用Vue多了,逐渐觉得这些概念没那么陌生了。但还是觉得各种开源的Virtual Dom,React等对Virtual Dom的实现的源码不太容易读懂,源码的注释不全是一大障碍,直到遇到了snabbdom,才开始觉得有深究其源码的冲动。

为什么是snabbdom?

因为snabbdom是用typescript写的,如果有了解过typescript的话就会知道,各种类型、参数、接口、函数和类的定义都非常严谨,如果是按照typescript的规范来写,加上命名规范的话,根本不需要写注释就可以让人轻松读懂代码。微软发明的typescript填补了javascript这种弱语言的各种不规范的缺点,让人可以像强语言一样来写JS真的很了不起。Snabbdom另外一个特点就是代码组织、模块化非常清晰。让人更容易上手。还有,如果有看过Vue源码的话就会发现,新版的Vue使用的Virtual Dom就源于snabbdom。

为什么需要Virtual Dom?

我们先来看看来自一个比较早的几乎与react同时实现virtual dom开源库: https://github.com/Matt-Esch/virtual-dom 对virtual dom介绍。

virtual-dom
A JavaScript DOM model supporting element creation, diff computation and patch operations for efficient re-rendering

Motivation
Manual DOM manipulation is messy and keeping track of the previous DOM state is hard. A solution to this problem is to write your code as if you were recreating the entire DOM whenever state changes. Of course, if you actually recreated the entire DOM every time your application state changed, your app would be very slow and your input fields would lose focus.

virtual-dom is a collection of modules designed to provide a declarative way of representing the DOM for your app. So instead of updating the DOM when your application state changes, you simply create a virtual tree or VTree, which looks like the DOM state that you want. virtual-dom will then figure out how to make the DOM look like this efficiently without recreating all of the DOM nodes.

virtual-dom allows you to update a view whenever state changes by creating a full VTree of the view and then patching the DOM efficiently to look exactly as you described it. This results in keeping manual DOM manipulation and previous state tracking out of your application code, promoting clean and maintainable rendering logic for web applications.

其大意,什么是Virtual Dom呢?Virtual Dom就是一个Dom的模型或者我们习惯叫的虚拟Dom,支持虚拟Dom元素创建,到虚拟Dom元素比较变化计算,到把变化应用到真实Dom元素,最后实现Dom的重新高效渲染。动机是什么呢?能够解决Dom的操控难、前后变化难以跟踪、Dom的高效局部更新问题和其实还有两个上面没提到的痛点被解决了,就是可以支持server side渲染及支持Native端渲染(react-native,weex和小程序的实现依赖于Virtual Dom)。

Virtual Dom 主要涉及的概念

  • VNode(virtual node / virtual tree)--虚拟DOM。
  • H(hyperscript)--最原始的定义是“Create HyperText with JavaScript.”,在snabbdom里面,h函数是生成虚拟DOM的函数。而不是生成HyperText超文本或者实实在在的Dom节点。
  • Patch--使用diff算法来比较旧VNode及新的VNode之间的差异然后执行Patch Operation或者叫Patch函数来高效更新Dom节点。
  • htmlDomApi--一些操作Dom函数的工具集合,在Patch函数里面会大量用到。
  • Thunk--在react全家桶中经常会看到Thunk这概念,在计算机语言中是传名调用的意思,但如果按我个人的理解就是中间件的概念,更通俗一点就是在某函数的每次输入与输出之间,预加一个自定义的拦截处理函数(thunk函数),先对输入的参数进行预处理再作为输入,这样当然输出的结果就依赖于thunk函数了。react-thunk中间件的作用也类似,让redux可以支持dispatch一个异步函数(不使用的话,只能支持dispatch同步的action)。而在snabbdom里,thunk主要用于优化性能,在每次patch之前先拦截一下判断VNode状态数据有没有变化,如果没有变化就不需要执行patch操作了。
  • Hooks--一些勾子函数,可以绑定到VNode里面的整个生命周期里面,使得支持类似Vue这样的框架的生命周期之间相应关联。

作者: 博主

Talk is cheap, show me the code!

发表评论

电子邮件地址不会被公开。

Captcha Code