在 Vue.js 中,如果你在对象上添加新属性而界面没有刷新,这可能是由于Vue的响应性系统的特性所导致的。Vue在初始化时会对数据进行响应式转换,这意味着只有在初始时存在的属性才会被监听,后来添加的属性不会自动触发视图更新。
我们从一个例子开始:
<template>
<div>
<p v-for="(value, key) in items" :key="key">
{{ value }}
</p>
<button @click="handleclick">按钮</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
items: {
oldProperty: '旧属性'
}
}
},
methods: {
handleclick() {
this.items.newProperty = '新属性'
console.log(this.items) // 输出带有 newProperty 的 items
}
},
}
</script>
点击按钮,发现结果不及预期,数据虽然更新了(log打印出了新属性),但页面并没有更新。
有几种方法可以解决这个问题:
• 方法1:使用全局的Vue.set()
<template>
<div>
<p v-for="(value, key) in items" :key="key">
{{ value }}
</p>
<button @click="handleclick">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
items: {
oldProperty: '旧属性'
}
}
},
methods: {
handleclick() {
this.$set(this.items, 'newProperty', '新属性')
}
}
}
</script>
• 方法2:使用展开运算符,给对象重新赋值
<template>
<div>
<p v-for="(value, key) in items" :key="key">
{{ value }}
</p>
<button @click="handleclick">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
items: {
oldProperty: '旧属性'
}
}
},
methods: {
handleclick() {
const properties = {
'newProperty1': '新属性1',
'newProperty2': '新属性2',
'newProperty3': '新属性3'
}
this.items = {
...this.items,
...properties
}
}
}
}
</script>
• 方法3:使用Object.assign(),给对象重新赋值
<template>
<div>
<p v-for="(value, key) in items" :key="key">
{{ value }}
</p>
<button @click="handleclick">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
items: {
oldProperty: '旧属性'
}
}
},
methods: {
handleclick() {
const properties = {
'newProperty1': '新属性1',
'newProperty2': '新属性2',
'newProperty3': '新属性3'
}
this.items = Object.assign({}, this.items, properties)
}
}
}
</script>
• 方法4:采取$forceUpdate()进行强制刷新 (不建议)
<template>
<div>
<p v-for="(value, key) in items" :key="key">
{{ value }}
</p>
<button @click="handleclick">按钮</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
items: {
oldProperty: '旧属性'
}
}
},
methods: {
handleclick() {
this.items.newProperty = '新属性'
this.$forceUpdate()
}
},
}
</script>
小结
如果为对象添加少量的新属性,可以直接采用 Vue.set()
如果需要为新对象添加大量的新属性,则通过 展开运算符 或 Object.assign() 创建新对象
如果你实在不知道怎么操作时,可采取 $forceUpdate() 进行强制刷新 (不建议)
Tips:Vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式。