Vue uses defineProperty to implement the listener function. But when you modify an array object using methods like push, POP, etc., setter methods are not triggered, that is, the array changes are not listened for. Vue rewrites the prototype methods push, POP, Shift, unshift, splice, sort, reverse.

Overwrite __proto__ for real arrays, as in

arr.__proto__=arrayMethods;
Copy the code

Make arrayMethods’ __proto__ point to array. prototype

const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);
Copy the code

Define some methods on arrayMethods

const methodsToPatch = [
  'push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'
]
Copy the code
methodsToPatch.forEach(function (method) {
  const original = arrayProto[method] 
  def(arrayMethods, method, functionmutator (... Args) {// Define methods like push on arrayMethods const result = original.apply(this, args) // Constructor inherits these methods on array prototypes const ob = this.__ob__let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break} // Add the following functions on the basis of the original push etc. // monitor changes and notify changesif (inserted) ob.observeArray(inserted)  
    ob.dep.notify()
    return result
  })
})
Copy the code

At this point, the structure of an array object is shown below. When we access the push method, we get the overwritten method, which adds listeners to the newly inserted element and notifies the change. When you access a method like map, you access arr.proto.proto.map(arrayMethods.proto.map), which is the map method on the prototype.