虚拟DOM的实现原理

虚拟DOM的实现原理

虚拟DOM是什么

定义:用普通的js对象来描述DOM对象

虚拟DOM实例:

{
  sel:"div", //选择器
  data:{}, //模块中所需要的数据
  children:undefined, //对应的子节点(children和text属性互斥)
  text:"hello", //标签中的文本(children和text属性互斥)
  elm:undefined, //当前vnode对象转换之后的DOM元素
  key:undefined //唯一标识当前的vnode对象(唯一标识节点),string/number
}
image-20220317162237726

VNodeData接口

  • 用来约束data对象的类型。即VNode接口中的data属性
image-20220317214308807

为什么使用虚拟DOM

为什么使用虚拟DOM:

  • 复杂视图情况下提升渲染性能
    • 创建虚拟DOM的成本比真实DOM小很多(因为虚拟DOM、真实DOM的成员分别为6、上百个)
  • 解决跟踪状态变化问题(数据发生变化,可以获取上一次的状态,不用把页面上的所有元素删除再重新创建)
  • 跨平台(因为虚拟DOM是js对象, 可以对虚拟DOM做任何的编程处理)
    • 浏览器平台渲染DOM
    • 服务端渲染SSR(Nuxt.js:是基于vue的SSR /Next.js:是基于react的SSR )
      • 服务端渲染就是把虚拟DOM转换成普通的HTML字符串
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

前端时代回顾:

  • 刀耕火种
    • 手动操作DOM、解决浏览器兼容性问题
  • jquery
    • 简化DOM的复杂操作,跨多种浏览器工作
    • jQuery是一个快速、小且功能丰富的JavaScript库。它使用一个易于使用的API,可以跨多种浏览器工作,从而使HTML文档遍历和操作、事件处理、动画和Ajax等工作变得更加简单。jQuery结合了多功能性和可扩展性,改变了数百万人编写JavaScript的方式。
  • 项目复杂化
    • 既要操作数据又要操作DOM
  • 为了简化DOM的复杂操作
    • MVVM框架解决视图和状态同步(当数据发生变化自动更新视图,视图发生变化自动同步数据)
  • 简化视图操作
    • 模板引擎可以简化视图操作,没办法跟踪状态(数据发生变化,无法获取上一次的状态,只能把页面上的所有元素删除再重新创建)
  • 解决跟踪状态变化问题
    • 虚拟DOM,当状态改变的时候,不需要立即更新DOM,只需要创建一个虚拟DOM树来描述真实的DOM树,虚拟DOM内部会弄清如何有效的更新真实DOM(diff算法找到状态的差异),只更新变化的部分
      • 虚拟DOM可以维护程序的状态,跟踪上一次的状态
      • 通过比较前后2次状态差异更新真实DOM

虚拟DOM的实现原理

image-20220316154818833

snabbdom的作用:是一个注重简单性、模块化、具有强大特性和性能的虚拟DOM库

导入snabbdom

snabbdom的核心函数

  • init

    • 是一个高阶函数,接收一个数组作为参数,数组中加载的是snabbdom的模块
    • init函数返回一个patch函数:把虚拟DOM转换成真实DOM渲染到界面上
  • h(重要)

    • 用来创建虚拟节点,(经过设置,创建的节点会替换掉html中的
      )
    • 有多个参数
      • 传2参数时
        • 1:字符串类型,代表标签+选择器
        • 2
          • 如果是字符串:标签中的文本内容
          • 如果是数组:数组里的每一个元素都是一个vnode对象,可以继续调用h函数来创建
    • h(’!’):生成空的注释节点
  • vnode的作用:虚拟DOM,用来描述真实DOM

  • patch函数(重要):对比2个vnode,把2个vnode的差异更新到真实DOM上

    • 参数
      • 有2个参数,都是vnode。
        • 1:旧的vnode
          • 可以传递真实DOM,内部会把真实DOM转换成vnode再对比
        • 2:新的vnode
    • 返回值
      • 返回新的vnode,返回的vnode会作为下一次再调用patch时的旧的vnode

snabbdom模块

模块的作用

  • Snabbdom的核心模块只能对vnode进行操作,不能处理DOM元素的属性/样式/事件等(可以通过Snabbdom自带的模块实现)
  • Snabbdom的模块是用来扩展Snabbdom本身的功能的
    • 类似于插件机制,也可以创建自定义模块来处理自己的逻辑
  • Snabbdom中模块的实现是通过注册全局的钩子函数来实现的
    • 全局钩子函数:是vnode的整个生命周期的过程中被触发的函数

官方提供的模块(不需记忆只需看懂)

  • attributes
    • 设置vnode对应的DOM元素的属性,使用的是DOM的标准方法set attributes实现的
    • 模块内部会对dom元素的布尔类型的属性作判断(如selected、checked)
  • props
    • 和attributes类似,设置DOM元素的属性,
    • 不同的是
      • props是通过 对象.属性 设置的
      • 内部不会处理布尔类型的属性
  • dataset
    • 处理html5中data-这种自定义属性
  • class
    • 不是用来设置类样式的,用来切换类样式的
    • 设置类样式可以通过h函数的第一个参数
  • style
    • 设置行内样式,容易设置过渡动画,内部注册了transation end事件
  • eventlisteners
    • 注册和移除事件

其他模块

  • hero:自定义模块
  • module:定义了模块中使用到的所有的钩子函数
    image-20220308090715750
  • h:定义了h函数,用来创建vnode对象
  • hooks:定义了vnode的生命周期中用到的所有钩子函数
  • htmldomapi:对dom api的包装,里面是创建元素、删除元素等
  • init:定义了init函数,init用来加载模块、dom api并返回一个patch函数
  • is:辅助的模块,导出了2个模块,用来判断数组和原始值的函数
  • gsx-global:是gsx的类型声明文件
  • gsx:用来处理gsx的
  • thunk:用来优化处理对复杂视图不可变值的优化
  • tovnode:提供了一个函数,可以把dom转换为vnode
  • vnode:定义了vnode的结构,是一个接口,规定了vnode对象应该有哪些成员

模块的使用步骤

  • 导入需要的模块
  • init()中注册模块
  • h()函数的第2个参数(对象形式)处使用模块

看Snabbdom源码的小目标

image-20220307213138402 image-20220317160036785

函数重载

  • 函数个数或参数类型不同的函数(和参数有关,和返回值无关)
  • js中没有重载的概念
  • TypeScript中有重载,不过重载的实现还是通过代码调整参数

看源码快捷键

  • 选中模块+F12 / 选中模块+ctrl+鼠标左键:定义到模块定义的位置
  • alt+← :返回刚才的位置
  • alt+→ :前进到刚才的位置
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值