vue中的虚拟dom和diff算法

本文介绍了Vue中虚拟DOM的概念,强调了其通过JS对象模拟DOM结构以提高性能的作用。文章引用了snabbdom库作为虚拟DOM的实现参考,并详细讲解了h函数用于创建虚拟节点的功能。接着,讨论了Diff算法,展示了如何通过该算法实现最小量更新,并通过实例解释了key在diff过程中的重要性。最后,概述了diff算法的工作原理,强调了它在同一层进行精细化比较以避免不必要的DOM操作。
摘要由CSDN通过智能技术生成


1. 虚拟DOM

JS引擎执行JS代码是很快的,比直接操作真实DOM要快的多。数据改变 --> 虚拟DOM(计算变更)—> 操作真实DOM —> 视图更新

在jquery时代,数据改变 —> 操作真实DOM —> 视图更新,是直接操作真实的DOM。vue框架引入了虚拟DOM

什么是虚拟DOM?

  • 虚拟DOM就是使用JS对象模拟真实的DOM结构,用JavaScript对象描述DOM的层次结构。DOM中的一切属性都在虚拟DOM中有对应的属性。
  • vue当中虚拟DOM的实现是参考一个库,snabbdom

为什么要有虚拟DOM

  • diff算法是发生在虚拟DOM上的,新虚拟DOM和老虚拟DOM进行diff(精细化比较),算出应该如何最小量更新,最后反映到真正的DOM上。

  • 从真实DOM变成虚拟DOM属于模板编译的内容。diff算法研究最小量更新,并将虚拟DOM变成真实的DOM

snabbdom库

  • snabbdom是著名的虚拟DOM库,是diff算法的鼻祖,Vue源码借鉴了 snabbdom
  • 在git上的snabbdom源码是用Typescript写的,git上并不提供编译好的Javascript版本。如果要直接使用build出来的JavaScript版的snabbdom库,可以从npm上下载: npm i snabbdom
  • snabbdom库是DOM库,不能在nodejs环境运行

h函数

h函数用来产生虚拟节点(vnode),由vnode组成的树就是虚拟DOM树

Vnode的优点

  1. 兼容性强,不受执行环境的影响。VNode因为是JS对象,不管Node还是浏览器,都可以统一操作,从而获得了服务端渲染、原生渲染、手写渲染函数等能力。
  2. 减少操作DOM,任何页面的变化,都只使用VNode进行操作对比,只需要在最后一步挂载更新DOM,不需要频繁操作DOM,从而提高页面性能。

虚拟节点有哪些属性

  • children: 值可能是undefined(是undefined表示没有子元素),也可能使数组
  • data: {}
  • elm: undefined。elm是undefined说明这个节点还没有在DOM树上
  • key: undefined
  • sel: “div”。选择器
  • text:文字描述

h函数可以产生虚拟节点,h函数可以嵌套使用,从而得到虚拟DOM树。第二个参数可以省略。第三个参数可以是文字、数组、或者h函数

patch函数,让虚拟结点上树

import {
   
  init,
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
  h,
} from "snabbdom";

// 创建patch函数
let patch = init([classModule, propsModule, styleModule, eventListenersModule]);

// 创建一个虚拟节点,但是它还没有在DOM树上。要想把它放在DOM树上,需要patch函数
let vnode1 = h('a', {
   props: {
   href: 'http://www.baidu.com',target:'_blank'}}, '百度一下')

let container = document.getElementById('container');
// 让虚拟结点上树,patch函数只能让一个虚拟结点上树。如果vnode2和vnode3要上树,需要把这个注释掉
patch(container, vnode1);

let vnode2 = h('div',{
   class:{
   "box":true}},'我是一个盒子');

let vnode3 = h('ul',{
   },[
    h('li','苹果'), // 第二个参数可以没有
    h('li','香蕉'), // 这里已经调用了h函数
    h('li',[
        h('p',{
   },'桔子'),
        h('p',{
   },'哈哈')
    ]),
    h('li','西瓜'),
    h('li',h('span','火龙果')) // 如果children只有一个子元素,第三个参数可以不要数组
]);

手写h函数

h函数有很多种用法,第二个和第三个参数都可以省略。h函数源码中对参数是否存在做了很多的判断,在这里 我们只实现有三个参数的h函数。

// vnode.js
export default function vnode(sel, data, children, text, elm) {
   
  return {
   sel, data, children, text, elm};
}

                
Vue虚拟DOM是一种将真实DOM抽象成JavaScript对象的技术。它通过在内存构建一个虚拟DOM树来代替直接操作真实的DOM,从而提高性能和可维护性。\[1\] 在更新虚拟DOM时,Vue使用了diff算法来比较新旧虚拟DOM的差异,并尽可能地减少对真实DOM的操作。diff算法会逐个比较新旧虚拟DOM的节点,找到它们在旧虚拟DOM的位置,然后根据差异进行相应的操作,如移动、插入或删除节点。Vuediff算法进行了优化,使得算法的时间复杂度降低到O(n),其n是虚拟DOM的节点数量。\[1\]\[2\] 除了Vue,还有其他轻量级的虚拟DOM库,如SnabbdomSnabbdom也提供了一套简单的API,用于创建和操作虚拟DOM,并支持自定义模块来扩展功能。Snabbdom的设计思路与Vue虚拟DOM相似,都旨在提高Web应用程序的性能和可维护性。\[3\] #### 引用[.reference_title] - *1* *3* [【Vue学习】Vue原理—虚拟DOMdiff算法](https://blog.csdn.net/zx1041561837/article/details/129262979)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [vue虚拟domdiff算法](https://blog.csdn.net/weixin_54003465/article/details/130819020)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值