一、数组的变异(数组更新)
Vue.js 内部对被观察数组的变异方法 (mutating methods,包括 push() , pop() , shift() , unshift() , splic
e() , sort() 和 reverse() ) 进行了拦截,因此调用这些方法也将自动触发视图更新。
// 以下操作会触发 DOM 更新
demo.items.unshift({ childMsg: 'Baz' })
demo.items.pop()
// vue 2.6 // src/core/observer/array.js const arrayProto = Array.prototype; // 获取数组原型对象 const arrayMethods = Object.create(arrayProto); // 生成一个新对象,且__proto__ 指向 数组原型对象 const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']; /** * Intercept mutating methods and emit events */ methods.forEach(method => { const original = arrayProto[method]; let val = function mutator (...args) { const result = original.apply(this, args); //缓存原始方法 let inserted = null; switch (method) { case 'push': inserted = args; break; case 'unshift': inserted = args; break; case 'splice': inserted = args.slice(2); // array.splice(start[, deleteCount[, item1[, item2[, ...]]]]) [item]) break; } if (inserted) observeArray(inserted); // 获取插入的值,并设置响应式监听 notify(); // 通知依赖像更新 return result; } Object.defineProperty(arrayMethods, method, { value: val, writable: true, configurable: true, enumerable: true }) }) const observeArray = function observeArray (inserted) { // 简写,[具体实现](https://github.com/vuejs/vue/blob/2.6/src/core/observer/index.js) console.log(inserted); //新增的元素形成的数组 console.log('响应式监听数组'); } const notify = function notify () { console.log('视图更新了'); }
在Vue现有阶段中,对响应式处理利用的是Object.defineProperty对数据进行拦截,而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,所以我们需要对这些操作进行hack,让vue能监听到其中的变化。