一、为什么要重写数组方法?
Vue 为了实现响应式数据绑定,需要能够捕获到数据的变化,以便在数据发生改变时自动更新视图。JavaScript 中的数组是引用类型,所以常规的引用跟踪机制不能捕获数组内部的变化。因为Vue的响应式是通过 Object.defineProperty()实现的,这个api没办法监听数组长度的变化,也就没办法监听数组的新增。所以为了更友好的操作数组并触发响应式检测,Vue对改变原数组(数组本身)的方法进行了重写。
Vue通过原型拦截的方式重写了数组的7个方法,首先获取到这个数组的Observer。如果有新的值,就调用observeArray对新的值进行监听,然后调用notify,通知render watcher,执行update。
二、vue重写数组的七个方法分别是哪些?
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
说明:vue只重写了这7个方法,使用其它数组方法不会主动触发试图更新,例如 concat、slice 等,如果需要触发更新,我们可以使用Vue.set() 或 this.$set() 方法手动触发更新。另外,Vue3处理响应数据使用了Proxy,系统会自动捕获这些操作,并在数据变化时触发视图更新,所以不需要重写数组方法。
三、重写数组方法源码
// 获取数组的原型Array.prototype
var arrayProto = Array.prototype
// 新建一个继承于Array的对象
var arrayMethods = Object.create(arrayProto)
// 列出需要重写的数组方法名
var methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse",
]
// 遍历上述数组方法名,依次将上述重写后的数组方法添加到arrayMethods对象上
methodsToPatch.forEach(function (method) {
// 缓冲原始数组的方法
var original = arrayProto[method]
// 利用Object.defineProperty对方法的执行进行改写
def(arrayMethods, method, function mutator(val) {
var args = [],
len = arguments.length;
while (len--) args[len] = arguments[len]
// 执行原数组方法
var result = original.apply(this, args)
var inserted
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
break;
}
// 在此处进行通知
return result
})
})
// 进行监听
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}
具体来说,当调用重写的数组方法时,Vue 会执行以下步骤:
1.调用原始的数组方法,例如 push()、pop()、splice() 等。
2.在执行数组方法后,Vue 检测到数组发生了变化。
3.Vue 发出通知,触发视图的重新渲染,确保视图与数据保持同步。
这种重写机制使得开发者在操作数组时无需手动去触发视图更新,Vue 自动为你处理了这部分逻辑。文章来源:https://www.toymoban.com/news/detail-650889.html
说明:这些重写仅适用于通过 Vue 实例声明的数组。如果你直接使用原生的数组方法,Vue 将无法捕获到变化,可能导致视图不更新。文章来源地址https://www.toymoban.com/news/detail-650889.html
到了这里,关于vue 重写数组的七个方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!