Vue中的this.$set()用于解决数据更新后页面没有更新的问题,因为Vue2中的双向数据绑定是通过object.defineproperty()实现的。通过get和set方法,获取时触发get,更改时触发set。但是对于对象属性的删除和添加与根据数组的下标去修改数据的时候是没办法实现响应式的。一般通过this.$set解决,对于删除也有对应的this.$delete实现。
一、用this.$set()解决对象属性添加与删除的响应式
原代码:
<template>
<div>
<div>{{ obj }}</div>
<button @click="changObj">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
obj:{name:'皮卡丘'},
newObj:{}
}
},
methods:{
changObj(){
this.obj.age=17
console.log(this.obj);//{ "name": "皮卡丘","age": 17}
}
}
}
</script>
<style>
</style>
会发现对象属性更改了,但页面没更新,我们打开控制台可以发现:
会发现name属性是(...)的形式而我们新加的值并不是这样的,这是为什么呢?跟响应式有什么关系呢?其实很简单,原因是在Vue执行过程中会对data里面的属性进行递归的操作,给每个属性通过 object.defineproperty()添加get和set方法,从而实现响应式,由于我们的name是对象原有的属性,所以会有get跟set方法,(...)点开就可以看到name属性的值,点击的过程会触发name的get方法,我们新增的属性没有经过Vue处理,也就没有get和set方法了,也就是说没有响应式,我们可以通过this.$set()方法进行处理,使新增的属性具有响应式,其原理是给新增的属性绑定set与get方法。向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。
改造后代码:
<template>
<div>
<div>{{ obj }}</div>
<button @click="changObj">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
obj:{name:'皮卡丘'},
newObj:{}
}
},
methods:{
changObj(){
this.$set(this.obj,'age',17)
console.log(this.obj);//{ "name": "皮卡丘","age": 17}
}
}
}
</script>
<style>
</style>
再次打开控制台就可以发现:
都具备响应式了。
同理删除也是:
<template>
<div>
<div>{{ obj }}</div>
<button @click="changObj">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
obj:{name:'皮卡丘'},
newObj:{}
}
},
methods:{
changObj(){
delete this.obj.name
console.log(this.obj);//{}
}
}
}
</script>
<style>
</style>
数据更改了页面没有更新。
改造后代码:
<template>
<div>
<div>{{ obj }}</div>
<button @click="changObj">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
obj:{name:'皮卡丘'},
newObj:{}
}
},
methods:{
changObj(){
// delete this.obj.name
this.$delete(this.obj,'name')
console.log(this.obj);//{}
}
}
}
</script>
<style>
</style>
二、用this.$set()实现数组的响应式问题
解决根据下标更改数组,数据丢失响应式问题。
源代码:
<template>
<div>
<div>{{ arr }}</div>
<button @click="changArr">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
arr:[0,1,2,3,4]
}
},
methods:{
changArr(){
this.arr[0]=5
console.log(this.arr);//[5,1,2,3,4] 数据更改了但页面没有更新
}
}
}
</script>
<style>
</style>
改造后代码:
<template>
<div>
<div>{{ arr }}</div>
<button @click="changArr">更改obj</button>
</div>
</template>
<script>
export default {
data(){
return{
arr:[0,1,2,3,4]
}
},
methods:{
changArr(){
this.$set(this.arr,'0',5)
console.log(this.arr);//[5,1,2,3,4] 数据更改页面更新
}
}
}
</script>
<style>
</style>