vue如何监听数组变化?
Vue.js观察数组变化主要通过以下7个方法(push、pop、shift、unshift、splice、sort、reverse)怎么实现?通过对data数据中数组的这7个方法进行重新包装(注意只是data数据中的数组)为什么不直接对Array.prototype的原型方法进行重新包装?因为不应该过多地去影响全局案例:const patchArray = (function () {const
·
Vue.js观察数组变化主要通过以下7个方法(push、pop、shift、unshift、splice、sort、reverse)
怎么实现?
通过对data数据中数组的这7个方法进行重新包装(注意只是data数据中的数组)
为什么不直接对Array.prototype的原型方法进行重新包装?
因为不应该过多地去影响全局
案例:
const patchArray = (function () {
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'reverse',
'sort'
];
//设置对象属性的工具方法
function def (obj, key, val) {
Object.defineProperty(obj, key, {
value: val,
enumerable: true,
writable: true,
configurable: true
});
}
const arrayProto = Array.prototype, //缓存Array的原型
arrayMethods = Object.create(arrayProto); //继承Array的原型
methodsToPatch.forEach(function (method, index) {
def(arrayMethods, method, function (...args) {
//首先调用Array原型的方法
const res = arrayProto[method].apply(this, args);
//data中每个数组都有一个__ob__的私有属性指向创建的Observer实例(有兴趣看看源码中的observe方法,这里不详述)
const ob = this.__ob__;
let inserted = null;
//记录插入的值
switch(method) {
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
if (inserted) {
//如果是调用了push、unshift、splice,则尝试对新插入的值进行响应式绑定,因为插入的值有可能是对象(Object)或者数组(Array)
ob && ob.observeArray(inserted);
}
console.log('数组发生改变了');
//向所有依赖发送通知,告诉它们数组的值发生变化了
ob && ob.dep.notify();
return res;
});
});
return function (target) {
//看看浏览器支不支持__proto__这个属性,通过改变__proto__的值,可以设置对象的原型
if ('__proto__' in {}) {
//将数组的原型指向arrayMethods,这样当数组调用上述的7个方法时,其实是调用arrayMethods中的方法而不是调用Array.prototype中的方法
target.__proto__ = arrayMethods;
} else {
//如果浏览器不支持__proto__,则设置数组对应的属性,这样当数组调用上述的7个方法时,其实是调用数组对应属性指向的方法
for (let i = 0, l = methodsToPatch.length; i < l; i++) {
let key = methodsToPatch[i];
def(target, key, arrayMethods[key]);
}
}
}
})();
//测试
let arr = [1, 2, 3];
patchArray(arr);
arr.push(4);
更多推荐
已为社区贡献2条内容
所有评论(0)