这里提供一份 Vue 源码学习关于对 Array
数据侦听实现的完整攻略。
概述
Vue 框架作为数据驱动的 MVVM 框架,在响应式数据更新时能够实现高效的性能优化,是设计优秀的前端框架之一。而在 Vue 的响应式系统中,“对数组的数据侦听”是一个重要的实现细节,它可以实现监听数组数据变化并动态的更新视图。这也是 Vue 与其他前端框架的一个区别。
数组侦听实现
在 Vue 中,对于需要侦听的对象,会通过 Object.defineProperty
方法 实现属性拦截,从而实现对该对象的监听。而对于数组,则通过重写数组的原型方法来实现对数组数据的侦听。
源码分析
首先,Vue 在初始化时会先判断是否支持使用原生 __proto__
属性。如果支持,Vue 会直接重写原型方法;否则,Vue 会创建一个新的对象,并将需要重写的数组原型方法挂载在该对象上,最后在数组对象上重新设置 __proto__
属性;
接着,针对要被重写的 原型方法 push
、pop
、shift
、unshift
、splice
、sort
和 reverse
,Vue对这些数组方法增加了一个或多个拦截器。如 push
方法如下:
// src/core/observer/array.js
const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
];
// 对数组对象的7个变异方法,添加拦截器
methodsToPatch.forEach(function (method) {
// 原始方法
const original = arrayProto[method];
// 覆盖数组原型方法
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args);
const ob = this.__ob__;
let inserted;
switch (method) {
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
// 对插入的新元素进行响应式处理
if (inserted) ob.observeArray(inserted);
// 通知依赖更新
ob.dep.notify();
return result;
});
});
我们可以看到,Vue 重写了数组的原型方法,并为数组的7个变异方法添加了拦截器。拦截器会拦截数组变化并进行响应式更新,通知依赖更新。
示例说明
我们来看一下一个实际的示例,这个示例是一个模板引擎库的源码(我翻译了一下),它基于 Vue 实现。在模板引擎中,我们可以使用 JavaScript 表达式,包括用于处理数组的方法。在下面的示例中,我们可以看到如何使用数组的 splice
方法来删除数组中的项:
<template>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
<button @click="deleteLastItem()">删除最后一个元素</button>
</template>
<script>
export default {
data() {
return {
list: ['苹果', '香蕉', '草莓']
}
},
methods: {
deleteLastItem() {
this.list.splice(this.list.length-1, 1)
}
}
}
</script>
上述示例中,我们使用 splice
方法从 list
数组中删除最后一个元素,删除后,Vue 会自动检测到该数组的数据变化,并执行相应的更新。
再来看一个使用 push
方法添加一个项的示例:
<template>
<button @click="addItem()">添加元素到数组中</button>
<div>
{{ list }}
</div>
</template>
<script>
export default {
data() {
return {
list: []
}
},
methods: {
addItem() {
this.list.push('新加入的元素')
}
}
}
</script>
我们可以通过上述示例看到,当我们使用 push
方法添加新项时,Vue 同样会自动响应式更新视图。
总结
通过以上分析,我们可以看出 Vue 在对数组进行操作时,会重写数组的原型方法,并在方法内添加响应式逻辑。这种方式能较为高效地实现局部更新,且在我们在使用 Vue 的过程中,我们可以像普通数组一样正常使用其方法,并且能自动地触发相应的更新,这也是 Vue 响应式能力的重要部分之一。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue源码学习之关于对Array的数据侦听实现 - Python技术站