什么是Virtual DOM

  • Virtual DOM(虚拟DOM),是由普通的JS对象来描述DOM对象
  • 真实DOM成员,如下代码打印结果会发现真实的DOM代码非常庞大

    1. // 真实DOM对象
    2. let element = document.querySelector('#app')
    3. let s = ''
    4. for (var key in element) {
    5. s += key + ','
    6. }
    7. console.log(s)
  • 使用Virtual DOM来描述真实DOM

    1. // 虚拟DOM
    2. {
    3. sel: 'div',
    4. data: {},
    5. children: undefined,
    6. text: 'Hello Virtual DOM',
    7. elm: undefined,
    8. key: undefined
    9. }

    为什么要使用Virtual DOM

  • 前端开发刀耕火种的时代

  • MVVM框架解决视图和状态同步问题
  • 模板引擎可以简化视图操作,没办法跟踪状态
  • 虚拟DOM跟踪状态变化
  • 参考github上virtual-dom的动机描述

    • 虚拟DOM可以维护程序的状态,跟踪上一次的状态
    • 通过比较前后两次状态差异更新真实DOM

      虚拟DOM的作用

  • 维护视图和状态的关系

  • 复杂视图情况下提升渲染性能
  • 跨平台

    • 浏览器平台渲染DOM
    • 服务器渲染SSR(Nuxt.js/Next.js)
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

      虚拟DOM库

  • Snabbdom

    • Vue.js 2.x内部使用的虚拟DOM就是改造的Snabbdom
    • 大约200SLOC(single line of code)
    • 通过模块可扩展
    • 源码使用TypeScript开发
    • 最快的Virtual DOM之一
  • virtual-dom
    • 最早的 Virtual DOM 开源库

      Snabbdom基本使用

      步骤(使用parcel的原因是比较简单,亦可用webpack)
      • 安装parcel
        • 创建 package.json yarn init -y

        • 本地安装 parcel yarn add parcel-bundler

      • 配置scripts

        • “scripts”: {

          1. "dev": "parcel index.html --open",
          2. "build": "parcel build index.html"

}

  • 目录结构

模块

  • 模块的作用
    • Snabbdom的核心库并不能处理DOM元素的属性/样式/事件等,可以通过注册Snabbdom默认提供的模块来实现
    • Snabbdom中的模块可以用来扩展Snabbdom的功能
    • Snabbdom中的模块的实现是通过注册全局的钩子函数来实现的
  • 官方提供的模块

    • attributes

      • 设置 DOM 元素的属性,使用 setAttribute ()
      • 处理布尔类型的属性
    • props

      • 和 attributes 模块相似,设置 DOM 元素的属性 element[attr] = value
      • 不处理布尔类型的属性
    • class

      • 切换类样式
      • 注意:给元素设置类样式是通过 sel 选择器
    • dataset

      • 设置 data-* 的自定义属性
    • eventlisteners

      • 注册和移除事件
    • style

      • 设置行内样式,支持动画
      • delayed/remove/destroy
  • 模块的使用步骤

    • 导入需要的模块
    • init()中注册模块
    • h()函数的第二个参数处使用模块

src目录

  1. h.ts h() 函数,用来创建 VNode
  2. hooks.ts 所有钩子函数的定义
  3. htmldomapi.ts DOM API 的包装
  4. is.ts 判断数组和原始值的函数
  5. jsx-global.d.ts jsx 的类型声明文件
  6. jsx.ts 处理 jsx
  7. snabbdom.bundle.ts 入口,已经注册了模块
  8. snabbdom.ts 初始化,返回 init/h/thunk
  9. thunk.ts 优化处理,对复杂视图不可变值得优化
  10. tovnode.ts DOM 转换成 VNode
  11. vnode.ts 虚拟节点定义
  12. ├─helpers
  13. attachto.ts 定义了 vnode.ts AttachData 的数据结构
  14. └─modules 所有模块定义
  15. attributes.ts
  16. class.ts
  17. dataset.ts
  18. eventlisteners.ts
  19. hero.ts example 中使用到的自定义钩子
  20. module.ts 定义了模块中用到的钩子函数
  21. props.ts
  22. style.ts

Snabbdom文档

  • 看文档的意义
    • 学习任何一个库都要先看文档
    • 通过文档了解库的作用
    • 看文档中提供的示例,自己快速实现一个demo
  • Snabbdom文档