Vue原理学习:vdom 和 diff算法(基于snabbdom)

2024-05-16 15:04

本文主要是介绍Vue原理学习:vdom 和 diff算法(基于snabbdom),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vdom 和 diff

背景

基于组件化,数据驱动视图。只需关心数据,无需关系 DOM ,好事儿。

但是,JS 运行非常快,DOM 操作却非常慢,如何让“数据驱动视图”能快速响应?


引入 vdom

用 vnode 表示真实 DOM 结构

 <div id="div1" class="container"><p>vdom</p><ul style="font-size: 20px"><li>a</li></ul></div>
 {tag: 'div',props: {className: 'container',id: 'div1'}children: [{tag: 'p',children: 'vdom'},{tag: 'ul',props: { style: 'font-size: 20px' }children: [{tag: 'li',children: 'a'}// ....]}]}

演示 vdom 的使用(对比不用 vdom 的情况)—— snabbdom 和 jquery


使用 vdom 能快速操作 DOM

  • JS 执行很快

  • DOM 操作很慢

如何让 DOM 操作最快?—— 尽可能减少 DOM 操作,只操作需要更新的,不做多余操作。

如何尽量减少 DOM 操作?—— 两个 vnode 进行 diff ,找出不同。diff 是 JS 执行,会很快。 (画图示例,两棵 vnode ,找出不同)


diff 算法概述

diff 算法是一个很广泛的,前端常见的例如文本 diff ,json 对象 diff ,还有这里的“树 diff”。

  • 文本 diff ,例如 linux 的 diff 命令

  • json diff ,例如 GitHub - cujojs/jiff: JSON Patch and diff based on rfc6902

  • 树 diff ,如 vdom diff

diff 两棵树的时间复杂度是 O(n^3)(不可用的复杂度),例如 diff(Tree1, Tree2)

  • 遍历 Tree1 ,每个节点都要和 Tree2 对比

  • 针对 Tree1 的节点,遍历 Tree2 每个节点和它对比

  • 重新排序

但是,vdom diff 算法做了几个改进,让复杂度变为 O(n)

  • 只比较同一层级

  • tag 或组件不相同的,直接删掉重建,不再继续深入比较

  • tag 或组件 & key ,两个都相同的,即认为是相同节点


diff 算法过程详解

snabbdom https://github.com/snabbdom/snabbdom 是一款比较简洁、高性能的 vdom lib vue2.x 的 diff 算法完全参考它。 即了解 snabbdom 的 diff 算法,也就了解 vue2.x 的 diff 算法。应该面试的 diff 算法问题足够了

基本流程
  • 回顾一下它的基本使用,找出核心的 API: h patch

  • 下载 snabbdom 源码

  • 查看源码

注意
  • 解读源码,只看主干和要点,不要去扣细节

  • 源码是 ts ,但不妨碍我们阅读,不要关注语法细节

h 函数

【功能】h 函数是一个工厂函数,根据传入的参数,生成 vnode 结构

源码在 src/h.ts

输入和输出 function h(sel: string, data: VNodeData, children: VNodeChildren): VNode;

返回 return vnode(sel, data, children, text, undefined);

vnode 函数

源码在 src/vnode.ts

返回 return {sel, data, children, text, elm, key};

这里可以结合 demo 中的断点来看数据结构。此时的 elem 应该是 undefined

text 和 children

一个元素或者有 contentText ,后者有 children ,两者不能共存 demo 中有示例

patch 函数

【功能】:patch 函数将 newVnode 更新到 vnode 或者 elem 上,patch 的过程也就是 diff 的过程。

判断了老节点是否存在,然后执行销毁或者创建,然后执行 patchVnode

源码 src/snabbdom.ts ,找到其中的 init 函数,最后返回的就是 patch 函数。

输入输出 function patch(oldVnode: VNode | Element, vnode: VNode): VNode

(画图:elem 和 oldVnode vnode 的关系) (要考虑第一个参数是 VNode 和 Element 两种情况)

patchVnode 函数

patchVnode 函数是对比 两个虚拟 dom 不同的地方, 同时 也是 递归 调用 updateChildren 的 函数

源码在 src/snabbdom.ts

先看 addVnodesremoveVnodes ,最后看 updateChildren

updateChildren 函数

key的重要性

源码在 src/snabbdom.ts

以 todo list 的 items 变化,为例,图解演示即可


总结

diff 算法中,细节不是关键例如“头头 头尾 对比”等,核心概念才是关键,如 h vnode patch key 等。 所有的 diff 算法,以及无论如何做优化,都离不开这些核心概念

这篇关于Vue原理学习:vdom 和 diff算法(基于snabbdom)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/995242

相关文章

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

使用vscode搭建pywebview集成vue项目实践

《使用vscode搭建pywebview集成vue项目实践》:本文主要介绍使用vscode搭建pywebview集成vue项目实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录环境准备项目源码下载项目说明调试与生成可执行文件核心代码说明总结本节我们使用pythonpywebv

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

CSS 样式表的四种应用方式及css注释的应用小结

《CSS样式表的四种应用方式及css注释的应用小结》:本文主要介绍了CSS样式表的四种应用方式及css注释的应用小结,本文通过实例代码给大家介绍的非常详细,详细内容请阅读本文,希望能对你有所帮助... 一、外部 css(推荐方式)定义:将 CSS 代码保存为独立的 .css 文件,通过 <link> 标签

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue

Vue中插槽slot的使用示例详解

《Vue中插槽slot的使用示例详解》:本文主要介绍Vue中插槽slot的使用示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、插槽是什么二、插槽分类2.1 匿名插槽2.2 具名插槽2.3 作用域插槽三、插槽的基本使用3.1 匿名插槽

springboot+vue项目怎么解决跨域问题详解

《springboot+vue项目怎么解决跨域问题详解》:本文主要介绍springboot+vue项目怎么解决跨域问题的相关资料,包括前端代理、后端全局配置CORS、注解配置和Nginx反向代理,... 目录1. 前端代理(开发环境推荐)2. 后端全局配置 CORS(生产环境推荐)3. 后端注解配置(按接口