什么是Vue2.x中Array的变化侦测?

对于编程概念的理解,一度让我回想起做数学题时的感受。

会,就是会。不会,就是不会。🤕

How

如何追踪变化

上篇传送门:什么是vue2.x中Object的变化侦测?

书中(🎤哪来的书?请查阅本文对应专栏)给出的解释是:在ES6之前,JavaScript并没有提供 元(猿)编程 的能力。即没有提供可以拦截原型方法的能力。

So,没有条件创造条件。在调用原型方法前设置路障,即 拦截器

What

拦截器可以是什么?

  • Object.defineproperty()
  • 覆写了的数组原型(数组变异)
  • ...(其他可以有,但不做讨论)👻

Why

为什么通过数组变异的方式来实现?

  • Object.defineProperty 支持数组吗---支持

  • 为什么选择覆写?简而言之,就是出于性能考虑

  • 性能考虑?【不好理解?🙄】那就引用下其他大佬的话术

如果你知道数组的长度,理论上是可以预先给所有的索引设置 getter/setter 的。

但是一来很多场景下你不知道数组的长度,二来,如果是很大的数组,预先加 getter/setter 性能负担较大。

如何实现拦截器

源码 进行了适当阅读,删减后的我的理解版本

  • 创建变量 copyArrayMethods,使其继承 Array.prototype
  • 在 copyArrayMethods 上使用 Object.defineProperty 方法,对可以改变数组自身内容的方法进行爆改(封装)⛏
  • 使用push方法 ---> 调用 copyArrayMethods.push ---> Object.defineProperty 里的函数 mutator
  • 图解如下:

使用拦截器覆盖Array原型

拦截器有了,如何生效?---> 覆盖到Array原型上

不能直接覆盖,会污染全局的Array,需要覆盖的范围仅限于需要被侦测的数据。

所以,在将数据转换成响应式的过程中,对数据过滤,把拦截器覆盖到需要转换成响应式数组的原型上即可。(代码请参考源码,这里仅做思路理解与阐述)

兼容性考虑

覆盖属性的过程中,需要使用到一个叫做__proto__ 的属性,并非所有的浏览器都对其百分百支持。所以要做对应的兼容处理,关键函数 protoAugmentcopyAugment 如下:

js 复制代码
/**
 * Augment an target Object or Array by intercepting
 * the prototype chain using __proto__
 */
function protoAugment (target, src: Object, keys: any) {
  /* eslint-disable no-proto */
  target.__proto__ = src
  /* eslint-enable no-proto */
}

/**
 * Augment an target Object or Array by defining
 * hidden properties.
 */
/* istanbul ignore next */
function copyAugment (target: Object, src: Object, keys: Array<string>) {
  for (let i = 0, l = keys.length; i < l; i++) {
    const key = keys[i]
    def(target, key, src[key])
  }
}

用图来理解即为:

Object和Array的对依赖的操作对比

类型 操作 位置
Object 收集依赖 getter
Object 触发依赖 setter
Array 收集依赖 getter
Array 触发依赖 拦截器

数组的依赖存在哪

答:Observer实例上。

原因:Observer实例,既可以被getter访问到,又可以被拦截器访问到。(这里不理解的jym建议看看相关文章的分析)

总结

欢迎留言讨论不同的理解思路~🤕

相关推荐
hoLzwEge12 小时前
解码 IDE 智能提示:jsconfig.json 辅助开发全攻略
前端·前端框架
慧一居士12 小时前
Element Plus 按需引入的配置使用说明和完整示例
前端·vue.js
gis开发之家15 小时前
《Vue3 从入门到大神35篇》Vue3 源码详解(五):effect 依赖收集原理——track 与 trigger 是如何工作的?
javascript·typescript·前端框架·vue3·vue3源码
橘子星16 小时前
我一个前端切图仔,凭什么能在浏览器里跑大模型?
前端·javascript·前端框架
CoderWeen16 小时前
我写了个能一步步点着看的 Dijkstra 可视化项目(Vue3 + Leaflet + Generator)
前端·javascript·vue.js
无人生还17 小时前
第 1 篇:从 Vue3 到 React 的思维转变
前端·vue.js·react.js
就业发动机17 小时前
我用 Tauri 做了一个约 1.5 MB 的开源屏幕标注工具:MarkerOn
vue.js·rust
爱分享的程序猿-Clark17 小时前
【前端分享】vue开发项目,如何实现 从A页面跳转到B页面,并传值!
前端·javascript·vue.js
徐小夕18 小时前
花了3天,我写了一款开源AI公众号编辑器
前端·vue.js·github
come1123419 小时前
Vue 2 与 Vue 3 语法区别及使用技巧
前端·javascript·vue.js