再谈vue中的differ算法

vue,differ,算法 · 浏览次数 : 44

小编点评

**Vue.js 中的 Diff 算法** Vue.js 中的 Diff 算法用于高效地比较新旧虚拟 DOM 树的差异,以减少 DOM 操作的次数,提高性能。 **Diff 算法的核心步骤:** 1. **比较根节点:**如果新旧根节点相同,则直接替换旧的根节点。 2. **比较子节点:**如果根节点相同,则比较子节点。使用双端比较策略,可以尽可能复用旧的节点,减少 DOM 操作的次数。 3. **添加或删除节点:**如果子节点中有更新的节点,则将其添加到真实的 DOM 树中。 **双端比较的优越性:** * 可以更快速地找到不同之处。 * 可以避免比较无用的节点。 **示例:** 假设我们有一个 Virtual DOM 树,其结构如下: ``` { tag: 'div', children: [ { tag: 'ul', children: [{ tag: 'li', text: 'Item 1' }, { tag: 'li', text: 'Item 2' }] }, { tag: 'button', text: 'Add Item' } ] } ``` 使用双端比较算法,可以同时从新旧两个树的顶部和底部开始比较节点,从而更快地找到不同之处。 **其他优化:** * 设置 `key` 属性可以帮助 Vue.js 识别哪些节点是稳定的,哪些是动态的。 * 使用 `shouldComponentUpdate()` 方法可以控制 diff 的执行时机。

正文

Differ算法

在 Vue 中,当数据变化时,Vue 会使用 Virtual DOM 和 diff 算法来尽可能地减少 DOM 操作的次数,以提高性能。

diff 算法是 Virtual DOM 实现中的核心算法之一,其主要作用是比较新旧虚拟 DOM 树的差异,并将差异应用到真实的 DOM 树上。Vue 使用的 diff 算法是基于两个前提:
1、Web 应用中 DOM 操作的性能瓶颈主要在于访问和修改 DOM 元素所带来的重绘(repaint)和重排(reflow)。
2、在 Web 应用中,相邻的 DOM 节点往往具有相同的父元素,因此对于相邻的 DOM 节点,我们可以一次性地将它们的修改应用到父元素中,从而减少 DOM 操作的次数。

基于以上前提,Vue 中的 diff 算法主要分为以下几个步骤:
1、首先比较两个根节点是否相同,如果不同,则直接将新的根节点替换旧的根节点。
2、如果根节点相同,则比较它们的子节点,这里采用了一种叫做“双端比较”的策略,即同时从新旧节点的头部和尾部开始比较,找到第一个不同的节点,然后进行更新。这种策略可以尽可能地复用旧的节点,减少 DOM 操作的次数。
3、如果子节点中有一方已经比较完了,而另一方还有剩余节点,则将剩余节点一次性地添加到真实的 DOM 树中。
总的来说,Vue 的 diff 算法采用了一种高效的策略,通过尽可能地复用旧的节点,减少 DOM 操作的次数,提高了应用的性能。同时,Vue 还提供了一些优化选项,比如设置 key 值来告诉 diff 算法哪些节点是稳定的,可以被复用,哪些是动态的,需要重新创建。

举个例子:

  <div id="app">
  <ul>
    <li v-for="item in items">{{ item }}</li>
  </ul>
  <button @click="addItem">Add Item</button>
</div>

我们在 Vue.js 中定义了一个数据 items,初始值为空数组,并且有一个 addItem 方法,可以向 items 数组中添加一个新的元素。此外,我们使用 v-for 指令来渲染 items 数组中的每个元素。

  new Vue({
  el: '#app',
  data: {
    items: []
  },
  methods: {
    addItem() {
      this.items.push(`Item ${this.items.length + 1}`);
    }
  }
})

现在,我们点击“Add Item”按钮时,会向 items 数组中添加一个新的元素,并更新界面。如果我们使用 Vue.js 的开发者工具来查看 Virtual DOM 的变化,可以看到 diff 算法是如何工作的。
假设我们已经添加了两个元素到 items 数组中,此时 Virtual DOM 的结构如下所示:

  {
  tag: 'div',
  children: [
    {
      tag: 'ul',
      children: [
        { tag: 'li', text: 'Item 1' },
        { tag: 'li', text: 'Item 2' }
      ]
    },
    { tag: 'button', text: 'Add Item' }
  ]
}

现在我们点击“Add Item”按钮,添加一个新的元素到 items 数组中,items 数组变为 ['Item 1', 'Item 2', 'Item 3'],此时 Virtual DOM 的结构变为:

{
  tag: 'div',
  children: [
    {
      tag: 'ul',
      children: [
        { tag: 'li', text: 'Item 1' },
        { tag: 'li', text: 'Item 2' },
        { tag: 'li', text: 'Item 3' }
      ]
    },
    { tag: 'button', text: 'Add Item' }
  ]
}

可以看到,diff 算法首先比较根节点,发现它们相同,然后比较子节点,发现旧的 Virtual DOM 中有两个 li 元素,新的 Virtual DOM 中有三个 li 元素,因此 diff 算法会在旧的 Virtual DOM 中复用前两个 li 元素,只创建一个新的 li 元素,并将其插入到正确的位置。
通过这个例子,我们可以更好地理解 Vue.js 中 diff 算法的工作原理。当我们修改数据时,Vue.js 会自动重新渲染组件,并使用 diff 算法来比较新旧 Virtual DOM 的差异,并将差异应用到真实的 DOM 树上。这样,我们就可以
实现高效的页面更新,同时减少不必要的 DOM 操作,提高了页面性能和用户体验。
需要注意的是,这只是 Vue.js 中 diff 算法的一个简单示例,实际上 diff 算法的实现要更加复杂。Vue.js 采用了一种优化的 diff 算法,称为“双端比较”,可以更加高效地处理大型的 Virtual DOM,而不会牺牲性能。
总之,Vue.js 中的 diff 算法是一个非常重要的部分,它为我们提供了高效的页面更新和优秀的性能。对于开发者来说,了解 Vue.js 中 diff 算法的工作原理可以帮助我们更好地理解 Vue.js 的核心原理,从而更好地编写高质量的 Vue.js 应用程序。

双端比较

Vue.js 中采用的“双端比较”算法是对传统的“单端比较”算法的一种优化,它能够更加高效地处理大型的 Virtual DOM 树。
传统的 diff 算法从根节点开始,逐级比较新旧两棵树的节点,直到找到不同之处,然后根据差异进行 DOM 更新。这种算法的缺点是,对于大型的 Virtual DOM 树,会比较耗时,因为算法需要比较所有的节点,即使这些节点是相同的。
“双端比较”算法的优化是同时从新旧两个树的顶部和底部开始比较节点。这样可以使得算法更快地找到不同之处,同时避免比较无用的节点。具体来说,算法会执行以下步骤:
1、从新旧两棵树的顶部开始,比较相同位置的节点。
2、如果找到不同之处,算法会停止比较顶部的节点,然后从底部开始比较相同位置的节点。
3、如果找到不同之处,算法会停止比较底部的节点。
4、然后,算法会计算出要更新的节点范围,并进行 DOM 更新。
举个例子,假设我们有以下的 Virtual DOM 树:

  {
  tag: 'div',
  children: [
    {
      tag: 'ul',
      children: [
        { tag: 'li', text: 'Item 1' },
        { tag: 'li', text: 'Item 2' },
        { tag: 'li', text: 'Item 3' }
      ]
    },
    { tag: 'button', text: 'Add Item' }
  ]
}

当我们向 items 数组中添加一个新的元素时,Virtual DOM 树变为:

 {
  tag: 'div',
  children: [
    {
      tag: 'ul',
      children: [
        { tag: 'li', text: 'Item 1' },
        { tag: 'li', text: 'Item 2' },
        { tag: 'li', text: 'Item 3' },
        { tag: 'li', text: 'Item 4' }
      ]
    },
    { tag: 'button', text: 'Add Item' }
  ]
}

使用“双端比较”算法,Vue.js 会同时从新旧两个树的顶部和底部开始比较节点。首先比较顶部的节点,发现它们是相同的。然后比较底部的节点,发现新的 Virtual DOM 树中有一个新的 li 元素,因此算法会停止比较底部的节点,并计算出要更新的节点范围为从第三个 li 元素到最后一个 li 元素。最后,算法会执行 DOM 更新操作。
通过使用“双端比较”算法,Vue.js 可以更快

与再谈vue中的differ算法相似的内容:

再谈vue中的differ算法

Differ算法 在 Vue 中,当数据变化时,Vue 会使用 Virtual DOM 和 diff 算法来尽可能地减少 DOM 操作的次数,以提高性能。 diff 算法是 Virtual DOM 实现中的核心算法之一,其主要作用是比较新旧虚拟 DOM 树的差异,并将差异应用到真实的 DOM 树上。

再谈量化策略失效的问题

更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流。 如何判断量化策略是否失效 我们在交易量化策略的时候,经常会遇到量化策略出现持续性的回撤。此时,必须考虑一种情况,即正在交易的策略可能失效了。于是,我们的首要工作是,判断这个量化策略是否失效。 判断量化交易

再谈23种设计模式(3):行为型模式(学习笔记)

行为型模式的关注点在于对象之间的通信和职责分配(描述结构模型中对象的动态特征)。行为型模式关注的是对象之间的交云和协作,即它们是如何相互作用的,以及如何分配职责和算法来完成任务。

再谈http请求调用(Post与Get),项目研发的核心一环

支持.Net Core(2.0及以上)与.Net Framework(4.0及以上) 【目录】 前言 Post请求 Get请求 与其它工具的比较 1【前言】 http请求调用是开发中经常会用到的功能。 在内,调用自有项目的Web Api等形式接口时会用到;在外,调用一些第三方功能接口时,也会用到,因

【转帖】再谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

https://www.zhoulujun.cn/html/theory/ComputerScienceTechnology/network/2015_0708_65.html 长文是对TCP IP的街剖析归类总结,就自己的经验再次回顾IP协议而写的归纳性笔记,助力初学者掌握。文有不妥之处,请查看原

kettle从入门到精通 第七十一课 ETL之kettle 再谈http post,轻松掌握body中传递json参数

场景: kettle中http post步骤如何发送http请求且传递body参数? 解决方案: http post步骤中直接设置Request entity field字段即可。 1、手边没有现成的post接口,索性用python搭建一个简单的接口,关键代码如下(安装python环境略): fro

kettle从入门到精通 第六十七课 ETL之kettle 再谈kettle阻塞,阻塞多个分支的多个步骤

场景:ETL沟通交流群内有小伙伴反馈,如何多个分支处理完毕之后记录下同步结果呢?或者是调用后续步骤、存储过程、三方接口等。 解决:使用步骤Blocking step进行阻塞处理即可。 1、 如下流程图中利用Blocking step步骤同时阻塞【模拟表输出1】和【模拟表输出2】两个步骤,只有当两个步

Python装饰器实例讲解(一)

Python装饰器实例讲解(一) 多种角度讲述这个知识,这是个系列文章 但前后未必有一定的顺承关系 部分参考网络 本文以一个小案例引出装饰器的一些特点,不涉及理论,后面再谈 案例 写一个代码来求一个数是否是质数 def is_prime(x): if x == 2 : return True eli

【论文阅读】自动驾驶光流任务 DeFlow: Decoder of Scene Flow Network in Autonomous Driving

再一次轮到讲自己的paper!耶,宣传一下自己的工作,顺便完成中文博客的解读 方便大家讨论。 Title Picture Reference and pictures paper: https://arxiv.org/abs/2401.16122 code: https://github.com/K

好用!这些工具国庆一定要研究下「GitHub 热点速览」

再过 3 天就要开始一年最长的假期——国庆长假了,这次除了宅家、出游之外,多了一个新选项:研究下哪些项目可以安排上,来辅助自己的日常开发。你觉得一周获得 4k star 的 hyperdx 如何,它能让你快速定位生产环境哪里有问题;不停机也能部署新服务的 kamal 也许可以上你的研究榜单。