vue数据更改视图不更新问题
在一个组件实例中,只有在data里初始化的数据才是响应的,Vue不能检测到对象属性的添加或删除,没有在data里声明的属性不是响应的。
Vue不允许在已经创建的实例上动态添加根级响应式属性,但是可以使用$set方法将相应属性添加到嵌套的对象上。
例子一:属性a是已经声明了的,是响应的;属性b没有提前声明,因此改变了属性b的值的时候,如果直接赋值 this.form.b = 'desc'
, 虽然打印出来的值是改变了的,但是视图并没有更新。需要用Vue.set(object, key, value)
【或 this.$set(object,key,value)
】 方法将响应属性添加到嵌套的对象上。注意:object 必须是在data中已经声明的对象。
<section>
<p>动态添加嵌套属性1:</p>
<p>a的值{{form.a}}</p>
<p>b的值{{form.b}}</p>
<el-button @click="changeA">改变A</el-button>
<el-button @click="changeB">改变B</el-button>
</section>
<script>
export default {
name: "layout",
data(){
return {
form:{
a:''//初始化
}
}
},
methods:{
changeA(){
this.form.a = 1
},
changeB(){
//this.form.b = 'desc' //无效
this.$set(this.form,'b','desc')//动态添加
//或者 Vue.set(vm.form,'b','desc')
}
}
}
</script>
例子二:Vue.set(object,key,value)
方法一次只能添加一个属性,如果需要向嵌套对象上添加多个属性,可以用Object.assign方法。object.assign方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。
vm.object = Object.assign( { } , vm.object , {a:' 1 ', b:' 2 ' })
注:object必须是已经声明的对象
<section>
<p>object.assign方法</p>
<p>{{form3.f1}}</p>
<p>{{form3.f2}}</p>
<el-button @click="changeForm3">添加多个属性</el-button>
</section>
export default {
name: "layout",
data(){
return {
form3:{}
}
},
methods:{
changeForm3(){
this.form3 = Object.assign({},this.form3,{f1:'f1',f2:'f2'})
}
}
}
例子三:利用索引直接设置一个项,不能直接触发状态更新。
通过改动两种方式改动数组时,Vue检测不到变动:1.利用索引直接设置一个项;2.修改数组长度。
<p v-for="(item,index) in trees" @click="changeMe(index)">这个是{{item}}</p>
export default {
name: "layout",
data(){
return {
trees:['a','b','c']
}
},
methods:{
changeMe(idx){
//this.trees[idx] = 'x'//无响应
this.$set(this.trees,idx,'x')//有响应
//this.trees.splice(idx,1,'x')//有响应
}
}
}
例子四:改变数组长度
<p v-for="(item,index) in trees">这个是{{item}}</p>
<el-button @click="changeLength">改变长度</el-button>
export default {
name: "layout",
data(){
return {
trees:['a','b','c']
}
},
methods:{
changeLength(){
//this.trees.length = 2//无响应
this.trees.splice(2)//有响应
}
}
}
set方法调用时,可以触发页面全部重新渲染。
比如在vue中有个data数组arr:
//arr=[1,2,3]
arr[1]='b'
console.log(arr) // [1,2,3]
Vue.set(arr,2,'c')
console.log(arr) // [1,b,c]
可以看出set触发了整个页面的重新渲染,连arr[1]='b’的效果也被重新渲染了。