我们都知道vue是用Object.defineProperty实现响应式的。但是Object.defineProperty实现响应式的时候有两个弊端:
1. 无法检测到对象属性的新增或删除
2. 不能监听数组的变化
当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue当你修改数组的长度时,例如:vm.items.length = newLength
一.对象:
接下来看一个例子,如果我们再Vue中想要给对象中添加一个属性,是什么样的结果呢?
<template>
<div id="app">
<ul>
<li v-for="val in obj">{{val}}</li>
</ul>
<button @click="addProperty">给对象添加属性</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
obj:{
name:'zs',
age:18,
sex:'男'
}
}
},
methods:{
addProperty(){
this.obj.school='北京大学';
console.log(this.obj)
}
}
}
</script>
从结果可以看到,本身obj对象中已经有新增的属性了,但是这个新增的属性并没有更新到试图中,
如果我们想要把对象中新增的属性页更新到试图中,那么就要用到 $set了
如果把以上代码改成$set添加
<template>
<div id="app">
<ul>
<li v-for="val in obj">{{val}}</li>
</ul>
<button @click="addProperty">给对象添加属性</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
obj:{
name:'zs',
age:18,
sex:'男'
}
}
},
methods:{
addProperty(){
this.$set(this.obj,'school','北京大学')
console.log(this.obj)
}
}
}
</script>
从输出的结果我们可以看出,新增的属性school不仅可以在对象中已经被添加上了,而且视图页更新了
二、对于数组
<template>
<div id="app">
<ul>
<li v-for="(val,index) in arr" :key="index">{{val}}</li>
</ul>
<button @click="addProperty">给数组添加值</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
obj:{
name:'zs',
age:18,
sex:'男'
},
arr:['a','b','c']
}
},
methods:{
addProperty(){
//使用下标修改数组中的某个个值
this.arr[0]='你好';
//修改数组的长度
this.arr.length=10;
console.log(this.arr)
}
}
}
</script>
从结果我们可以看到,控制台中的数组已经变化了,但试图中的数组并没有更新
接下来我们用$set
<template>
<div id="app">
<ul>
<li v-for="(val,index) in arr" :key="index">{{val}}</li>
</ul>
<button @click="addProperty">给数组添加值</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
obj:{
name:'zs',
age:18,
sex:'男'
},
arr:['a','b','c']
}
},
methods:{
addProperty(){
//使用下标修改数组中的某个个值
this.$set(this.arr,0,'你好')
//修改数组的长度
this.arr.splice(1)
console.log(this.arr)
}
}
}
</script>
我们发现结果也是可以改变的