Virtual DOM 的实现原理

什么是虚拟DOM

  •  Virtual DOM(虚拟DOM),是由普通的 JS 对象来描述 DOM对象。

为什么使用虚拟DOM 

 

虚拟 DOM 的作用 

  • 维护视图和状态的关系
  • 复杂视图情况下提升渲染性能
  • 除了渲染 DOM 以外,还可以实现 SSR(Nuxt.js/Next.js) 、原生应用(Weex/React Native)、小程序(mpvue/uni-app)

 

 Virtual DOM 库

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

 Snabbdom 基本使用

创建项目 

  • 打包工具用 parcel
  • 创建项目,并安装 parcel 

 

  • 配置 package.json 的scripts 

 

  • 创建目录结构 

 

 

  • 安装  Snabbdom :yarn add snabbdom

导入 Snabbdom 

  • Snabbdom 的官网 demo 中导入使用的是 commonjs 模块化语法,我们使用更流行的 ES6 模块
    化的语法 import
  • 关于模块化的语法请参考阮一峰老师的 Module 的语法  
  • ES6 模块与 CommonJS 模块的差异

    import { init , h , thunk } from 'snabbdom'
     
  •  Snabbdom 的核心仅提供最基本的功能,只导出了三个函数 init()h()thunk()
    • init() 是一个高阶函数,返回 patch()
    • h() 返回虚拟节点 VNode,这个函数我们在使用 Vue.js 的时候见过

 

  • thunk() 是一种优化策略,可以在处理不可变数据时使用

 代码演示 Snabbdom 

// var snabbdom = require('snabbdom)
//导入 snabbdom
import { h, init } from 'snabbdom'

//1. hello world
// 参数:数组,模块
// 返回值: patch函数,作用对比两个vnode的差异更新到真实 DOM
let patch= init([])
//第一个参数:标签 + 选择器
//第二个参数:如果是字符串的话就是标签中的内容
let vnode = h('div#container.cls', 'hello world')

let app = document.querySelector("#app")
//第一个参数:可以是DOM元素,内不会吧DOM元素转换成vnode
//第二个参数:vnode
//返回值:vnode
let oldVode = patch(app, vnode)

//假设的时刻
vnode = h('div', 'hello world snabbdom')

path(oldVode, vnode)

 模块

  •  Snabbdom 的核心库并不能处理元素的属性/样式/事件等,如果需要处理的话,可以使用模块

    常用模块  

  • 官方提供了 6 个模块
    • attributes
      • 设置 DOM 元素的属性,使用 setAttribute ()
      • 处理布尔类型的属性
    • props
      • attributes 模块相似,设置 DOM 元素的属性 element[attr] = value
      • 不处理布尔类型的属性
    • class
      • 切换类样式
      • 注意:给元素设置类样式是通过 sel 选择器
    • dataset
      • 设置 data-* 的自定义属性
    • eventlisteners
      • 注册和移除事件
    • style
      • 设置行内样式,支持动画
      • delayed/remove/destroy

    模块使用 

  • 导入需要的模块
  • init() 中注册模块
  • 使用 h() 函数创建 VNode 的时候,可以把第二个参数设置为对象,其他参数往后移

     代码演示

import { h, init } from 'snabbdom'

//1. 导入模块
import style from 'snabbdom/modules/style'
import eventlisteners from 'snabbdom/modules/eventlisteners'

//2. 注册模块
let patch = init([
    style,
    eventlisteners
])

//3. 使用 h() 函数的第二个参数传入模块需要的数据(对象)
let vnode = h('div', {
    style: {
        backgroundColor:'red'
    },
    on: {
        click:eventHandler
    }
}, [
    h('h1', 'hello snabbdom'),
    h('p', '这是p标签')
])

function eventHandler () {
    console.log('惦记我了')
}

let app = document.querySelector("#app")

patch(app, vnode)

 patch的整体过程

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值