如果想给已经声明好的实例新增data里的key,可以使用Vue.set,或者预先定义为undefined。
那如果data中有数组怎么办?对于数组来说长度是不定的,可以随时增加和删除。所以肯定无法提前定义好所有key。那么对于数组来说,就只能每次改变的时候都要使用Vue.set吗,这也太麻烦了。
new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods: {
setD() {
this.array[3] = "d";
}
}
}).$mount("#app");
点击按钮,会出现'd'吗?不会
因为数组其实也是对象,它的下标0,1,2...就是key。Vue只会对一开始定义的那些数组下标进行监控。别的都不知道,所以也就不会响应。
使用Vue.set(this.array,3,'d') 也不会自动监听和代理(原因未知)
尤雨溪做了一件事:篡改了数组的API。先说结果:
直接使用:this.array.push('d') 页面数组后边会成功出现'd'
array本来是一个普通的数组对象,但是经过new Vue之后,Vue就对数组进行了篡改。在array对象和Array函数中间插入了一个原型,即array->新原型->Array.
在这个新原型上边,他重新定义了7个push,pop之类和原来同名的API。这个新push会先调用原来的push,给数组增加一个值。然后,自动监听和代理新的key。
所以,我调用this.array.push时,会先把key:value放进数组,再自动监听和代理。这样页面就可以响应了。
我们看看现在的push是什么:console.log(this.array)
具体是怎么篡改的呢?