Vue—修改数据不渲染Dom问题
一、添加属性的问题<template><div><p v-for="(value,key) in item" :key="key">{{ value }}</p><button @click="addProperty">动态添加新属性</button></div></template><scrip
·
一、添加属性的问题
<template>
<div>
<p v-for="(value,key) in item" :key="key">
{{ value }}
</p>
<button @click="addProperty">动态添加新属性</button>
</div>
</template>
<script>
export default {
data:()=>{
item:{
oldProperty:"旧值"
}
},
methods:{
addProperty(){
this.item.newProperty = "新值" // 为items添加新属性
console.log(this.items) // 输出带有newProperty的items
}
}
};
</script>
这时候我们会遇到一个问题:在方法中修改变量时,log打印结果了,但是dom并没有重新渲染。
二、问题分析:
vue2是用过Object.defineProperty实现数据响应式,组件初始化才递归遍历item,这时候并没有给item的每个属性添加set和get方法,所有后来并没有给newVal设置成响应式数据,结果就是修改后不会视图更新。
const item = {}
Object.defineProperty(obj, 'oldProperty', {
get() {
console.log(`get oldProperty:${val}`);
return val
},
set(newVal) {
if (newVal !== val) {
console.log(`set oldProperty:${newVal}`);
val = newVal
}
}
})
}
三、解决方案
由于Vue已经不允许在已经创建的实例上添加新的响应式属性,所有可以采用以下三种方法:
-
Vue.set()
-
Object.assign()
-
$forcecUpdated()
(1)、Vue.set()
Vue.set( target, propertyName/index, value )
- 参数1:target:要修改的对象或数组
- 参数2:propertyName/index:属性或下标
- 参数3:value:修改后的value值
这里再次调用defineReactive方法,给新增属性设置成响应式,内部还是通过Vue.defineProperty实现属性拦截。
function set (target: Array<any> | Object, key: any, val: any): any {
...
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
(2)、Object.assign()
- 参数1:一个空对象,用来存放新增属性与原对象混合之后的对象
- 参数2:原来的对象
- 参数3:需要给对象新增的属性
this.item = Object.assign({},this.item,{newProperty:'新值'})
(3)、$forcecUpdated
在Vue实例添加这个方法
this.$forcecUpdated()
强制Vue实例进行重新渲染
四、小结。
- 如果需要添加少量属性,可直接采用Vue.set()
- 如果需要添加大量属性,就采用 Object.assign()
- 强制刷新采用$forcecUpdated()(不推荐)
PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式
更多推荐
已为社区贡献4条内容
所有评论(0)