Array.prototype.push.apply(arr1, arr2)无法自动触发DOM更新

使用多种方式对两个数组进行合并操作,为何有的不能自动触发DOM的更新?

<div id="app">
    <ul>
        <li v-for="item in list">
            {{item}}
        </li>
    </ul>
    <button v-on:click="concatArray()">合并数组</button>
</div>

var app = new Vue({
    el: '#app',
    data: function() {
        return {
            list: [1, 2, 3, 4],
            newList: [5, 6, 7, 8]
        }
    },
    methods: {
        concatArray: function() {
            // 可以触发dom更新
            this.list = this.list.concat(this.newList);
            // 可以触发dom更新
            this.list.push.apply(this.list, this.newList);
            // 不可以触发dom更新
            [].push.apply(this.list, this.newList);
            // 不可以触发dom更新
            Array.prototype.push.apply(this.list, this.newList);
        }
    }
});

我查看了Vue的文档,知道由于js的限制,Vue无法检测某些对数组的操作:

当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength

但是我费解的是,为什么 this.list.push.apply(this.list, this.newList) 可以,
Array.prototype.push.apply(this.list, this.newList) 却不可以。
这两种调用方式有什么本质的不同吗?
麻烦各位大神解答一下,非常感谢!

回答:

  1. 因为 this.list.push !== Array.prototype.pushthis.list.push指向的是vue重写过的方法
  2. 依据
    clipboard.png
  3. 相关源码可参考楼上的

回答:

图片描述

看了部分源码, vue有改写Array.prototype的方法来监控数据改变, 用原生的js没有办法监控到.

回答:

应该说是只有在vue已经进行观察的数组上调用的方法添加的数据才会被加上observer

回答:

可以参考下这两篇文章:JavaScript实现MVVM之我就是想监测一个普通对象的变化
Vue2.1.7源码学习

我们在 arr1.proto 与 Array.prototype 之间的链条中添加了一环 fakePrototype (假的原型),我们的思路是,在使用 push 等数组方法的时候,调用的是 fakePrototype 上的push方法,然后在 fakePrototype 方法中间接再去调用真正的Array原型上的 push 方法,同时监听变化

暂无评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注