Vue项目中:使用数组中的元素绑定 v-show,v-if 时的失效问题:this.$set(),Vue.set()

一、场景

循环一个二维数组,通过点击标题,用 v-show,v-if 判断详情是否展示。

二、问题查找

可能是设置值出了问题,用 this.$set( target, propertyName/index, value )实现

参数有三个:

  • 第一个参数是对象或数组

  • 如果是对象,第二个参数就是属性名;如果是数组,第二个参数就是数组的下标

  • 第三个参数是修改的值:如果是对象就是值,如果是数组可能是值,也可能是对象,如:{ id: 1, name: "姓名" }

  • 与 Vue.set() 的区别:组件中可以直接使用 this.$set(),如果使用 Vue.set(),就要 import Vue

三、当值是对象时

  • 定义

data() {
  return {
    info: { id: 1, title: '标题1', desc: '描述1', content: '内容1', flag: false}
  }
}
  • 使用

this.$set(this.info, "title", "修改后的标题")

四、Demo,当值是二维数组时

<template>
    <div class="app">
        <div class="box-content" v-for="(item, index) in content" :key="index">
            <div class="box-title" @click="clickBox(index)">
                <p>{
    
    {item.title}}</p>
                <p>{
    
    {item.desc}}</p>
            </div>
            <div class="box-detail" v-show="item.flag">
                <p>{
    
    {item.content}}</p>
            </div>
        </div>
    </div>
</template>

<script>
import axios from 'axios'
export default {
    name: 'app',
    data() {
        return {
            content: [
                {id: 1, title: '标题1', desc: '描述1', content: "内容1", flag: false},
                {id: 2, title: '标题2', desc: '描述2', content: "内容2", flag: false}
            ]
        }
    },
    methods: {
        clickBox(index) {
            /*
            //失败案例-1
            let flagValue = this.content[index].flag;
            flagValue = flagValue ? false : true;
            this.content[index].flag = flagValue;
            */
           
           /*
           //失败案例-2
           let flagValue = this.content[index].flag;
           flagValue = flagValue ? false : true;
           this.$set(this.content[index], 'flag', flagValue); //参数的值设置错误
           */
          
           /*
           //失败案例-3
           let flagValue = this.content[index].flag;
           flagValue = flagValue ? false : true;
           this.$set(this.content, index, {'flag', flagValue}); //这个相当于把this.content[index]的值重置,只剩flag了(其他的参数id,title,desc,content被清除了)
           */
          
            //点击行之后,一直是打开的,没有关闭其他行的操作
            let info = this.content[index]
            info.flag = info.flag ? false : true;
            this.$set(this.content, index, info); //使用数组控制v-show时必须使用这行代码
            
            //优化:点击当前行,关闭其他已经打开了的行,this.$set设置二维数组
            /*
            this.content.forEach((item, key) => {
                let change = false; //是否需要重置行数据
                if (key == index) { //判断当前点击的是否关闭
                    change = true;
                    item.flag = item.flag ? false : true;
                } else if (item.flag) { //如果其他数据是打开的,则关闭
                    change = true;
                    item.flag = false; //关闭其他的
                }
                if (change) {
                    this.$set(this.content, key, item); //设置某一行的所有值
                }
            });
            */
            
            //优化:点击当前行,关闭其他已经打开了的行,this.$set设置对象{}
            /*
            this.content.forEach((item, key) => {
                let change = false; //是否需要重置行数据
                let flag;
                if (key == index) { //判断当前点击的是否关闭
                    change = true;
                    flag = item.flag ? false : true;
                } else if (item.flag) { //如果其他数据是打开的,则关闭
                    change = true;
                    flag = false; //关闭其他的
                }
                if (change) {
                    this.$set(item, 'flag', flag); //设置某一行的flag值
                }
            });
            */
        },
    }
}
</script>

<style scoped>
*{
    padding: 0;
    margin: 0;
}

/* 样式自己写~ */


</style>

猜你喜欢

转载自blog.csdn.net/zyf971020/article/details/129199635