• vue 修改v-for 循环内的item数据视图不刷新


    需求

    修改v-for后得到的每一项内的某个数据,视图应当重新渲染

    如下面的代码

    ============================================
    这是父组件,给子组件传了一个 类型为
    interface DataType { title: string value: string show: boolean } 的数组

    <template>
        <Tree :options="dataSource" />
    </template>
    
    <script setup lang="ts">
    
    import Tree from '@/test/tree/Tree.vue'
    
    const dataSource = [
      {
        title: 'test1',
        value: 'test1',
        show: false
      },
      {
        title: 'test2',
        value: 'test2',
        show: false
      },
      {
        title: 'test3',
        value: 'test3',
        show: false
      }
    ]
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这是子组件

    <script lang="ts" setup>
    import { ref, toRefs } from 'vue'
    
    export interface DataType {
      title: string
      value: string
      show: boolean
    }
    
    //获取父组件传过来的props,并把数据变成响应式
    const props = defineProps<{ options: DataType }>()
    const { options: dataSource } = toRefs(props)
    
    //监听点击事件,并将循环后的item数据拿到并修改
    //按理来说数据已经用toRefs响应式监听了,修改数据视图应该改变才对
    //但是运行代码后视图并没有刷新
    const select = ref<DataType>({ title: '', value: '', show: false })
    const onClick = (item: DataType) => {
      item.show = !item.show
    }
    </script>
    
    <template>
      <div class="wrap">
        <div v-for="item in dataSource" :key="item.title">
          //点击这个元素将item上的属性show变成true或者false
          <div class="title" @click="onClick(item)">{{ item.title }}</div>
          //当item对象上的show属性为true时应该展示在视图上
          <div class="content" v-if="item.show">{{ item.value }}</div>
        </div>
      </div>
    </template>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    原因

    1.toRefs(props)确实会把这个对象编程响应式,所以监听元素click事件并修改item上的show时 dataSource的确会变
    2.dataSource变化后vue会重新执行这个组件内的代码获取新的虚拟dom然后去对比之前的dom再局部更新,
    3.关键再于vue重新执行这个组件内的代码时又拿到了父组件传来的数据,而这个数据自始自终是没有发生改变的,所以得到的虚拟dom永远和第一次渲染的dom一模一样所以视图永远不变

    解决方法

    父组件传数据的时候应该传个ref这能解决这个问题,但是vue不推荐子组件修改外部数据

    const dataSource = ref<DataType[]>([
      {
        title: 'test1',
        value: 'test1',
        show: false
      },
      {
        title: 'test2',
        value: 'test2',
        show: false
      },
      {
        title: 'test3',
        value: 'test3',
        show: false
      }
    ])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    思考

    当数据不是重父组件传过来的,修改v-for传回的数据会不会改变视图?

    答案是会的,只要这个数据用响应式ref或者reactive包裹就可以

    总结

    1.子组件不应该修改外部数据,应该通知父组件修改数据
    2.在不方便通知父组件修改数据时,父组件应该传ref给子组件不然子组件修改的数据永远数复制品,没有效果

  • 相关阅读:
    贝赛尔曲线 - Vue3实现加入购物车抛物线效果组件
    Java线程学习入门(二)
    Openresty(二十二)ngx.balance和balance_by_lua终结篇
    OneDrive下的OneNote扩容方法,及查看OneDrive容量的方法(详细图文教程)
    南大通用数据库-Gbase-8a-学习-07-集群节点缩容(8.6版本)
    中小学生使用全光谱台灯对眼睛好不好?2023口碑好的护眼台灯推荐
    C语言从入门到精通之【字符串】
    mapboxgl 绘制3d polygon
    [问题解决]vue前后端联调跨域问题解决
    力扣每日一题 矩阵中移动的最大次数 DP
  • 原文地址:https://blog.csdn.net/weixin_46787337/article/details/127869395