Vue源码——使用snabbdom实现虚拟DOM
snabbdom的基本使用一、关于虚拟DOM二、snabbdom的基本使用1、h()函数2、patch(oldVnode,newVnode)一、关于虚拟DOM虚拟DOM是关于Vue中特别重要的一个特点,与响应式系统息息相关,虚拟DOM实际上是一个javascript对象。虚拟DOM的作用:维持视图和状态的关系在复杂视图上才能够提升页面的渲染性能,在简单的视图上snabbdom会更加耗费资源除了渲染
·
一、关于虚拟DOM
虚拟DOM是关于Vue中特别重要的一个特点,与响应式系统息息相关,虚拟DOM实际上是一个javascript对象。
虚拟DOM的作用:
- 维持视图和状态的关系
- 在复杂视图上才能够提升页面的渲染性能,在简单的视图上snabbdom会更加耗费资源
- 除了渲染DOM之外,还可以实现服务端渲染SSR(Nuxt.js/Next.js)、原生应用(weex/React Native)、小程序(mpvue/uni-app)等
常用的虚拟DOM的库有两个
- virtual-dom
- Snabbdom
snabbdom介绍:
- Vue2.x 内部使用的虚拟DOM就是改造的Snabbdom
- 大约200SLOC(single line of code)
- 通过模块可扩展
- 源码使用Typescript开发
- 最快的virtual DOM之一
二、snabbdom的基本使用
方便起见,我这里使用的环境是Vue的脚手架,直接在main.js当中操作
附上一个基本案例:
import {h,thunk,init} from 'snabbdom';
let patch = init([]);//[]用于传入模块
//对比虚拟dom和真实dom(比较是是将真实dom转化为虚拟dom) 并返回一个虚拟dom
//div#inner.outer 创建div节点 hello World节点内容
let Vnode = h('div#inner.outer',[
// 创建多个子元素,使用[]
h('p','我是p标签'),
h('i','我是斜体')
]);// h函数用于创建虚拟dom
let app = document.getElementById('app')
let oldNode = patch(app,Vnode);//在app中放入 虚拟dom Vnode
注释已附上,需要注意的点是我这里使用的是0.7.4版本,目前已更新的版本为1.0.1,1.0.1版本的导入不同,如上图导入方式仅0.7.4以下版本可用,因为1.0.1版本模块发生了一个比较大的变化。
snabbdom核心:
- 使用h()函数创建JavaScript对象(VNode)描述真实DOM
- init()设置模块,创建patch()
- patch()比较新旧VNode
- 把变化内容更新到真实DOM树上
1、h()函数
h()函数介绍:
- h()最早见于hyperscript,使用JavaScript创建超文本
- Snabbdom中的h()函数不是用于创建超文本,而是创建VNode
函数重载:
准确来说,同名函数根据参数个数和类型的不同执行不同的代码这就是函数重载。
JavaScript中没用重载的概念,Typescript中有
例:
function add(a,b){
return a+b;
}
function add(a,b,c){
return a+b-c;
}
h()函数用法:
let Vnode = h('div#inner.outer',[
// 创建多个子元素,使用[]
h('p','我是p标签'),
h('i','我是斜体')
]);// h函数用于创建虚拟dom
第一个参数指定创建的元素,元素id,元素类等
第二个参数为元素的内容,可以使用中括号表示多个子元素
h()函数最后有这样一层代码
他返回了一个vnode函数,那么想了解的可以去看一看源代码,h()创建节点的主要方法就是vnode函数。
2、patch(oldVnode,newVnode)
patch()的执行流程:
打补丁,把新节点中变化的内容渲染到真实DOM,最后返回新节点作为下一次处理的旧节点
- 对比新旧Vnode是否相同节点(节点的key和sel相同)
- 如果不是相同节点,删除之前的内容,重新渲染
- 如果是相同节点,在判断新的VNode是否有text,如果有并且和oldVnode的text不同,直接更新文本内容
- 如果新的VNode有children,判断子节点是否有变化,判断子节点的过程使用的就是diff算法
- diff过程只进行同层级比较
更多推荐
已为社区贡献3条内容
所有评论(0)