首页 > 语言 > JavaScript > 正文

Vue源码学习之关于对Array的数据侦听实现

2024-05-06 15:40:19
字体:
来源:转载
供稿:网友

摘要

我们都知道Vue的响应式是通过Object.defineProperty来进行数据劫持。但是那是针对Object类型可以实现, 如果是数组呢? 通过set/get方式是不行的。

但是Vue作者使用了一个方式来实现Array类型的监测: 拦截器。

核心思想

通过创建一个拦截器来覆盖数组本身的原型对象Array.prototype。

拦截器

通过查看Vue源码路径vue/src/core/observer/array.js。

/** * Vue对数组的变化侦测 * 思想: 通过一个拦截器来覆盖Array.prototype。 * 拦截器其实就是一个Object, 它的属性与Array.prototype一样。 只是对数组的变异方法进行了处理。*/function def (obj, key, val, enumerable) {  Object.defineProperty(obj, key, {   value: val,   enumerable: !!enumerable,   writable: true,   configurable: true  })}// 数组原型对象const arrayProto = Array.prototype// 拦截器const arrayMethods = Object.create(arrayProto)// 变异数组方法:执行后会改变原始数组的方法const methodsToPatch = [  'push',  'pop',  'shift',  'unshift',  'splice',  'sort',  'reverse']methodsToPatch.forEach(function (method) {  // 缓存原始的数组原型上的方法  const original = arrayProto[method]  // 对每个数组编译方法进行处理(拦截)  def(arrayMethods, method, function mutator (...args) {   // 返回的value还是通过数组原型方法本身执行的结果   const result = original.apply(this, args)   // 每个value在被observer()时候都会打上一个__ob__属性   const ob = this.__ob__   // 存储调用执行变异数组方法导致数组本身值改变的数组,主要指的是原始数组增加的那部分(需要重新Observer)   let inserted   switch (method) {    case 'push':    case 'unshift':     inserted = args     break    case 'splice':     inserted = args.slice(2)     break   }   // 重新Observe新增加的数组元素   if (inserted) ob.observeArray(inserted)   // 发送变化通知   ob.dep.notify()   return result  })})

关于Vue什么时候对data属性进行Observer

如果熟悉Vue源码的童鞋应该很快能找到Vue的入口文件vue/src/core/instance/index.js。

function Vue (options) { if (process.env.NODE_ENV !== 'production' &&  !(this instanceof Vue) ) {  warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options)}initMixin(Vue)// 给原型绑定代理属性$props, $data// 给Vue原型绑定三个实例方法: vm.$watch,vm.$set,vm.$deletestateMixin(Vue)// 给Vue原型绑定事件相关的实例方法: vm.$on, vm.$once ,vm.$off , vm.$emiteventsMixin(Vue)// 给Vue原型绑定生命周期相关的实例方法: vm.$forceUpdate, vm.destroy, 以及私有方法_updatelifecycleMixin(Vue)// 给Vue原型绑定生命周期相关的实例方法: vm.$nextTick, 以及私有方法_render, 以及一堆工具方法renderMixin(Vue)export default Vue            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选