在 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实现数据响应式的,直接动态添加新属性仍可以实现数据响应式。