踩坑日记之Vue循环嵌套层级过深,视图更新不及时

3,736 阅读1分钟

efb55274d44740358b51d7700783fda4_th.png

踩坑日记 --【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>

综上所述:三种方法都是可以解决问题的,但是推荐使用【方法二】最为合理!