vdom

背景:数据驱动视图,有效控制DOM的操作
虚拟dom库:https://github.com/snabbdom/snabbdom
DOM操作会非常耗费性能
js模拟DOM结构,计算出最小变更,操作DOM

  1. // <div id="d1" class="container">
  2. // <p>vdom</p>
  3. // <ul style="font-size:20px;">
  4. // <li>a</li>
  5. // </ul>
  6. // </div>
  7. const vdom = {
  8. tag: 'div',
  9. props: {
  10. className: 'container',
  11. id: 'd1'
  12. },
  13. children: [
  14. {
  15. tag: 'p',
  16. children: 'vdom'
  17. },
  18. {
  19. tag: 'ul',
  20. props: {style: 'font-size: 20px'},
  21. children: [
  22. {
  23. tag: 'li',
  24. children: 'a'
  25. }
  26. ]
  27. }
  28. ]
  29. }
  • 用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-compilerhttps://www.npmjs.com/package/vue-template-compiler
模板不是html,html本身没有判断/循环/求值操作,所以需要转化为vnode代码(js代码执行)
问题:组件渲染和更新过程?
js的with语法:用来引用某个特定对象中已有的属性

  1. const obj = {
  2. a: 100,
  3. b: 200
  4. }
  5. with(obj) {
  6. console.log(a); // 100
  7. console.log(b); // 200
  8. console.log(c); // 会报错
  9. }
  • 改变{}内自由变量的查找规则,当做obj的属性来查找
  • 如果找不到匹配的属性,会报错
  • 要慎用,它打破了作用域规则,易读性变差

模板编译为render函数,执行render函数返回的是vnode
基于vnode再执行patch和diff算法

此处是个性能优化的点 使用webpack vue-loader,会在开发环境下编译模板(而运行时编译会很慢)

render函数可代替模板

渲染和更新(异步渲染)

注意:模板未用到的属性,和视图没关系,也不会触发getter,setter

初次渲染过程

  1. 解析模板为render函数(在开发环境中已完成,vue-loader)
  2. 触发响应式,为data中的属性添加getter, setter
  3. 执行render函数,生成vnode,执行patch函数,patch(elm, vnode)

更新过程

  1. 修改data属性后,触发setter(已被在getter中已被监听)
  2. 重新执行render函数,生成newVnode
  3. 执行patch函数,patch(vnode, newVnode)(diff算法)