一、什么是响应式
看下面代码,如果修改了vm.n,那么界面中的n就会发生改变来做出响应
const vm=new Vue({data:{n:0}})
二、vue中data的bug
代码一
new Vue({
data:{},
template:`
<div>{{n}}</div>
`
}).$mount("#app")
此时页面不会显示内容,同时报错:n没有定义但是引用了
代码二
new Vue({
data:{
obj:{
a:0//obj.a会被Vue监听并且代理
}
},
template:`
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods:{
setB(){
this.obj.b=1;//页面会显示1吗
}
}
}).$mount("#app")
此时页面不会显示1,因为obj.b从一开始就不存在
解决方法Vue.set
new Vue({
data:{
obj:{
a:0//obj.a会被Vue监听并且代理
}
},
template:`
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods:{
setB(){
Vue.set(this.obj,'b',1);
}
}
}).$mount("#app")
作用是
- 新增加一个key
- 自动创建代理和监听
- 触发UI更新,但不会立即更新 //这是vue的自动作用
如果data中有数组怎么办
看以下代码
new Vue({
data:{
array:["a","b","c"]
},
template:`
<div>
{{array}}
<button @click="setD>set d</button>
</div>
`,
methods:{
steD(){
this.array[3]="d";//这样页面仍然不会显示d
//数组中array:[0:"a",1:"b",2:"c",length],添加之后检测不到
this.$set(this.array,3,"d");//这样就可以显示d,但是实际上没办法提前先将数据写好
}
}
}).$mount("#app");
在上面的代码中,若data是数组,使用传统方法无法获得d;使用Vue.set则可以,但是实际上我们无法获取提前数组的长度
new Vue({
data:{
array:["a","b","c"]
},
template:`
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods:{
setD(){
this.array.push("d");
console.log(this.array)
}
}
}).$mount('#app')
这时,打开控制台看array的方法时,发现数组的方法新增了一层。 看以下代码
class VueArray extends Array{
push(..args){
const oldlength=this.length//this当前数组
super.push(...args)
for(let i=oldLength;i<this.length;i++){
Vue.set(this,i,this.[i])
}
}
}
总结
对象在新增的key
- Vue没有办法事先监听和代理,需要通过set来新增key,创建监听和代理,更新UI
- 最好提前把属性都补充好,不用新增key值
- 但若为数组,通常无法直接补充好值
数组新增key
- 同样可以用set新增key,且创建监听和代理,更新UI
- 不过尤雨溪篡改了数组7个API方便对数组进行增删
- 新API会自动处理监听和代理,更新UI