踩坑日记 --【Vue循环嵌套层级过深,给循环数据item添加自定义变量,操作变量后,视图更新不及时的问题解决方案】
背景
<template>
<div>
<div
v-for="(item, index) in detailData.planConfigs"
:key="index"
class="detail-box"
>
<div class="detail-title">
<div>
<el-button type="primary" @click="item.packUp = !item.packUp">
收起
</el-button>
</div>
</div>
<el-collapse-transition>
<div v-show="item.packUp">
<div>内容</div>
</div>
</el-collapse-transition>
</div>
</div>
</template>
export default {
data() {
return {
detailData: {
planConfigs: [
{
name: 'name',
value: 'value'
}
]
}
}
},
mounted() {
// 给原数据加了一个展示收起的控制器
this.detailData.planConfigs.forEach((item) => {
item.packUp = true
})
}
}
</script>
大概就是这么个场景,当我点击【展开 | | 收起】按钮时,【packUp】修改成【false】了,但是展开收起失效。
问题
循环嵌套层级太深,视图不更新
【this.detailData】已经是 【packUp=false】的新数据,但是视图没更新,template 还是旧数据渲染!
解决问题
方法一:this.$forceUpdate()
// 修改【展开||收起】的事件
// 定义展开收起的方法。使用this.$forceUpdate()让页面强制刷新
packUpFn(item) {
item.packUp = !item.packUp
// 官方说如果你现在的场景需要用forceUpdate方法 ,那么99%是你的操作有问题
this.$forceUpdate()
},
方法二:this.$set
// 修改【packUp】的自定义方式
// Vue 中有两种类型的变量:响应式变量和非响应式变量。
// 因为 packUp 是自定义加进去的变量,属于非响应式变量,如果你修改了非响应式变量,Vue 并不会监测到它们的变化,所以页面不会改变
// 如果需要使一个非响应式变量变成响应式变量,可以使用 this.$set 方法
// 使用方法:this.$set(对象,添加的key',属性值)
this.detailData.planConfigs.forEach((item) => {
this.$set(item, 'packUp', true)
})
方法二:绑定key属性
// 给渲染的dom绑定key属性,这样 Vue 就会认为这是不同的template
<template>
<div>
<div
v-for="(item, index) in detailData.planConfigs"
:key="index"
class="detail-box"
>
<div class="detail-title">
<div>
<el-button type="primary" @click="item.packUp = !item.packUp">
收起
</el-button>
</div>
</div>
<el-collapse-transition>
<div v-show="item.packUp" :key="index">
<div>内容</div>
</div>
</el-collapse-transition>
</div>
</div>
</template>
综上所述:三种方法都是可以解决问题的,但是推荐使用【方法二】最为合理!