vdom
背景:数据驱动视图,有效控制DOM的操作
虚拟dom库:https://github.com/snabbdom/snabbdom
DOM操作会非常耗费性能
js模拟DOM结构,计算出最小变更,操作DOM
// <div id="d1" class="container">
// <p>vdom</p>
// <ul style="font-size:20px;">
// <li>a</li>
// </ul>
// </div>
const vdom = {
tag: 'div',
props: {
className: 'container',
id: 'd1'
},
children: [
{
tag: 'p',
children: 'vdom'
},
{
tag: 'ul',
props: {style: 'font-size: 20px'},
children: [
{
tag: 'li',
children: 'a'
}
]
}
]
}
- 用js模拟DOM结构
- 新旧vnode对比,得出最小的更新范围,最后一次更新DOM
- 数据驱动视图,有效控制DOM的操作
h,vnode,patch,diff,key
交叉对比,先对比首首,尾尾,首尾,尾首对比,如果都不命中,则对比key在不在当前旧节点中,减少循环次数**
diff算法(O(n))
https://github.com/snabbdom/snabbdom
vdom中最核心,最关键的部分
- 只比较同一层级,不跨级比较
- tag不相同,则直接删掉重建,不再深度比较(else)
- **tag和key两者都相同,则认为是相同节点,不再深度比较(sameVNode函数)
模板编译
vue-template-compiler
:https://www.npmjs.com/package/vue-template-compiler
模板不是html,html本身没有判断/循环/求值操作,所以需要转化为vnode代码(js代码执行)
问题:组件渲染和更新过程?
js的with语法:用来引用某个特定对象中已有的属性
const obj = {
a: 100,
b: 200
}
with(obj) {
console.log(a); // 100
console.log(b); // 200
console.log(c); // 会报错
}
- 改变
{}
内自由变量的查找规则,当做obj的属性来查找 - 如果找不到匹配的属性,会报错
- 要慎用,它打破了作用域规则,易读性变差
模板编译为render函数,执行render函数返回的是vnode
基于vnode再执行patch和diff算法
此处是个性能优化的点 使用webpack vue-loader,会在开发环境下编译模板(而运行时编译会很慢)
render函数可代替模板
渲染和更新(异步渲染)
注意:模板未用到的属性,和视图没关系,也不会触发getter,setter
初次渲染过程
- 解析模板为
render
函数(在开发环境中已完成,vue-loader) - 触发响应式,为data中的属性添加
getter, setter
- 执行
render
函数,生成vnode
,执行patch
函数,patch(elm, vnode)
更新过程
- 修改data属性后,触发setter(已被在
getter
中已被监听) - 重新执行
render
函数,生成newVnode
- 执行
patch
函数,patch(vnode, newVnode)
(diff算法)