# Vue
# 响应式/双向绑定
# Vue2
数据劫持+观察者模式
# 数据劫持
当面试官问你 Vue 响应式原理,你可以这么回答他 (opens new window)
Object.defineProperty
将属性进行劫持
每个属性都拥有自己的 dep 属性,存放他所依赖的 watcher(依赖收集)
当某个属性修改时,触发 dep.notify()
通知每个需要更新的 watcher
Observer 负责将数据转换成 getter/setter 形式; Dep 负责管理数据的依赖列表;是一个观察者模式,上游对接 Observer,下游对接 Watcher Watcher 是实际上的数据依赖,负责将数据的变化转发到外界(渲染、回调); 首先将 data 传入 Observer 转成 getter/setter 形式;当 Watcher 实例读取数据时,会触发 getter,被收集到 Dep 仓库中;当数据更新时,触发 setter,通知 Dep 仓库中的所有 Watcher 实例更新,Watcher 实例负责通知外界
# Vue3
effect 副作用函数 替代 Vue2 的 watcher 来触发修改时的渲染
# diff
15 张图,20 分钟吃透 Diff 算法核心原理,我说的!!! (opens new window)
# Vue2
Diff 算法是一种对比算法。对比两者是旧虚拟 DOM 和新虚拟 DOM,对比出是哪个虚拟节点更改了,找出这个虚拟节点,并只更新这个虚拟节点所对应的真实节点,而不用更新其他数据没发生改变的节点,实现精准地更新真实 DOM,进而提高效率
原理:
Diff 算法比较只会在同层级进行, 不会跨层级比较。 所以 Diff 算法是:深度优先算法
updateChildren:
首尾指针法 双端比较算法
交叉对比 4 次
如果元素相同 指针移动
用 index 做 key
先比对 key 的值 如果相同 做比对 元素一直 并且没变 就不进行变更元素直接复用元素
相同 key 的节点会去进行 patchVnode 更新文本 如果结点变了 还是会更新
所以 唯一 key 的好处就是 当元素就算是进行了 patchVnode,也不会执行里面复杂的更新操作
介绍比对时间
# Vue3
深入浅出虚拟 DOM 和 Diff 算法,及 Vue2 与 Vue3 中的区别 (opens new window)
- 事件缓存
会先判断事件是否被缓存
- 添加静态标记
对于单个有动态绑定的元素来说,我们可以在编译时推断出大量信息 去给元素一个标记 判断他是哪一种动态类型 结点如果没有动态数据 会被标记为静态结点 HOISTED = -1
- 静态提升
模板里面没有动态变量
- patchKeyedChildren
一个区块内部的树结构打平
包含多个根节点的模板被表示为一个片段 (fragment),大多数情况下,我们可以确定其顺序是永远不变的,所以这部分信息就可以提供给运行时作为一个修补标记
template-explorer (opens new window)
去头尾的最长递增子序列算法
解析 Vue3.0 的 dom-diff 核心算法 (opens new window) 最长递增子序列的作用是找到最少移动次数