由于Object.defineproperty方法无法监听到数组和对象内的新增变化,所以vue2重写了常用的数组方法来使数组更新时能触发页面更新,对于对象的更新则采用this.$set的方法,使得对象更新时同时触发视图更新,这个之后再谈,今天我们来看一下vue内部是怎么重写常用的数组方法的。 1.vue2重写了哪些数组方法? 如下图,一共7中常用数组方法(来自源码)
var methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
];
也就意味着,如果使用这7种以外的数组方法更新数组,且需要视图也更新,则需要使用this.$set。 2.怎么重写数组方法 在重写之前先进行了以下两个步骤:
var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
arrayProto用来存储原生js的数组方法,用于接下来的遍历,arrayMethods定义一个空对象用来存放vue重写的数组方法以避免污染Array.prototype上的数组方法。 接下来是重写数组方法:
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function (method) {
// cache original method
var original = arrayProto[method];
def(arrayMethods, method, function mutator () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var result = original.apply(this, args);
var ob = this.__ob__;
var inserted;
switch (method) {
case 'push':
case 'unshift':
inserted = args;
break
case 'splice':
inserted = args.slice(2);
break
}
if (inserted) { ob.observeArray(inserted); }
// notify change
ob.dep.notify();
return result
});
});
由上述代码可见,由于push、unshift、splice会让数组索引发生改变,所以需要手动触发observer,这里的方法是定义一个inserted来控制是否触发响应式更新,如果为true,则用ob.observeArray(inserted);
来手动给新插入的值设置响应式监听,再用ob.dep.notify()
通知依赖更新,最后返回原生数组方法处理后的值 return result
。
3.相关知识点:
3.1 def方法源码,在数组方法的重写中,用到了该方法来定义vue自己的一些数组方法,便于vue对一些需要重写的数组方法进行数据劫持。
function def (obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
});
}
3.2 observeArray方法的源码,在数组方法重写中,用于将新增的数组元组变成响应式的。
Observer.prototype.observeArray = function observeArray (items) {
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
};
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!