# Vue

# 响应式

# Vue2

数据劫持+观察者模式持

当面试官问你 Vue 响应式原理,你可以这么回答他 (opens new window)

Object.defineProperty递归对每一个属性进行劫持

对象属性需要提前定义

初始化的时候直接递归了整个对象的属性监听,vue3 的话是触发 get 的时候才深层次递归到对应到对象深层次属性的的监听

每个属性都拥有自己的 dep 属性,存放他所依赖的 watcher(依赖收集)

当某个属性修改时,触发 dep.notify() 通知每个需要更新的 watcher

Observer 负责将数据转换成 getter/setter 形式; Dep 负责管理数据的依赖列表;是一个观察者模式,上游对接 Observer,下游对接 Watcher Watcher 是实际上的数据依赖,负责将数据的变化转发到外界(渲染、回调); 首先将 data 传入 Observer 转成 getter/setter 形式;当 Watcher 实例读取数据时,会触发 getter,被收集到 Dep 仓库中;当数据更新时,触发 setter,通知 Dep 仓库中的所有 Watcher 实例更新,Watcher 实例负责通知外界

# Vue3

俗易懂的 Vue3 响应式核心原理解析 (opens new window)

  1. 使用 proxy 拦截对象 不用像 vue2 对数组或者对象新增的属性特殊处理
  2. effect 副作用函数 当属性改变的时候再次触发一次。 替代 Vue2 的 watcher 来触发修改时的渲染
  3. track 和 trigger 封装 effect
    • track 创建一个 WakeMap 收集每一个对象的作为属性, 每一个对象的属性都有一个 Set 收集副作用函数数组

Proxy // Reflect 成对使用

# diff 算法

React、Vue2、Vue3 的三种 Diff 算法 (opens new window)

# Vue2 中的 Diff

什么是虚拟 DOM: 一个用来表示真实 DOM 的对象

什么事 Diff 算法:比对新旧虚拟 DOM,快速识别他们的差异,精准修改真实 DOM

原理:

Diff 算法比较只会在同层级进行, 不会跨层级比较。 所以 Diff 算法是:深度优先算法 O(n)

path 方法:对比当前同层的虚拟节点是否为同一种类型的标签

  • 是:继续执行 patchVnode 方法进行深层(深度优先,递归到叶子结点)比对
  • 否:没必要比对了,直接整个节点替换成新虚拟节点

sameVnode:sameVnode 方法判断是否为同一类型节点

patchVnode : 都有子节点 对比子节点 updateChildren

updateChildren:

首尾指针法 双端比较算法

交叉对比 4 次

如果元素相同 指针移动

用 index 做 key

先比对 key 的值 如果相同 做比对 元素一直 并且没变 就不进行变更元素直接复用元素

相同 key 的节点会去进行 patchVnode 更新文本 如果结点变了 还是会更新

所以 唯一 key 的好处就是 当元素就算是进行了 patchVnode,也不会执行里面复杂的更新操作

介绍比对时间

key 会随着 index 一起改变,但是子内容还是改变了,最终还是会更新虚拟结点,没有达到复用的效果。

# 在 Vue 中为什么不推荐用 index 做 key (opens new window)

因为当移动发生的时候,index 会重新渲染,导致 key 虽然和新旧结点一致,但是内容还是发生了改变,所以需要重新渲染。

# Vue3 Diff

update 性能提升了 1.3~2 倍

ssr 性能提升了 2~3 倍

深入浅出虚拟 DOM 和 Diff 算法,及 Vue2 与 Vue3 中的区别 (opens new window)

Vue3 中 Diff 的不同:

  • 事件缓存:会先判断事件是否被缓存
  • 添加静态标记:对于单个有动态绑定的元素来说,我们可以在编译时推断出大量信息 去给元素一个标记 判断他是哪一种动态类型 结点如果没有动态数据 会被标记为静态结点 HOISTED = -1
  • 静态提升:模板里面没有动态变量
  • patchKeyedChildren

一个区块内部的树结构打平

包含多个根节点的模板被表示为一个片段 (fragment),大多数情况下,我们可以确定其顺序是永远不变的,所以这部分信息就可以提供给运行时作为一个修补标记

template-explorer (opens new window)

去头尾的最长递增子序列算法

解析 Vue3.0 的 dom-diff 核心算法 (opens new window)

最长递增子序列的作用是找到最少移动次数

# React 和 Vue 的异同

你不知道的 React 和 Vue 的 20 个区别 (opens new window)

尤雨溪国外教程:亲手带你写个简易版的 Vue! (opens new window)