Vue2实现数组监听原理

2,370 阅读1分钟

一、Vue2中通过Object.defineProperty getter setter  实现对象的监听

Object.defineProperty监听弊端: 无法监听属性的添加或者移除;无法监听数组索引直接赋值;无法监听修改数组的长度

二、解决对象属性监听

对于对象属性的监听,vue提供了set  delete方法

三、解决数组监听

修改数组的继承关系,重写方法,进行拦截调用。

修改后的继承关系为:arr(数组对象)   ->  自定义的对象(他的隐式原型对象__proto__指向数组的显示原型对象prototype) ->   Array.prototype

这个自定义的对象继承了Array的方法重写了push,pop,shift,unshift,splice,sort,reverse

const ARRAY_METHODS = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse] 
const array_methods = Object.create(Array.prototype)
ARRAY_METHODS.formEach(method => {
   array_methods[methos] = function() {
      console.log(argument)
      console.log('调用的是拦截的方法')
      Array.from(arguments).forEach(arg => {
         console.log('监听当前的参数')  
      })
      // 当监听动作完成再进行函数调用
      Array.prototyoe[method].apply(this, arguments)
   }
})
  1. 如果浏览器支持__proto__,则采用修改原型链的方式

    //.........

    // 如果监听动作发生的时候,属性key的值value为数组 if (Array.isArray(value)) { value.proto = array_methods // .... }

   2. 如果浏览器不支持__proto__,则采用混入发将方法拷贝到对象上面取

// 如果监听动作发生的时候,属性key的值value为数组
if (Array.isArray(value)) {
  // getOwnPropertyNames返回的是对象所有自己的属性包含不可枚举
  // Object.keys则返回的是所有可枚举的属性即enumerable: true
  const array_keys = Object.getOwnPropertyNames(array_methods)
  array_keys.forEach(key => {
    Object.defineProperty(value, key, {
      configurable: true,
      writable: true,
      enumerable: true,
      value: array_methods[key]
    })
  })
}

四、VUE3中的实现

vue3中采用了Proxy对象的方式,实现对对象的拦截以及自定义操作。