• 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给子组件不然子组件修改的数据永远数复制品,没有效果

  • 相关阅读:
    <二叉树及模拟实现>——《Data Structure in C Train》
    【LeetCode高频100题】1 - ?
    centos7安装python3.7
    Java并发编程学习6-同步工具类和并发容器
    React 全栈体系(十三)
    Effective C++ 规则39:明智而谨慎的使用private继承
    机器学习案例(四):LSTM股价预测
    修复版知宇发卡企业级发卡平台完整源码/多商户入驻+对接微信公众号+对接免签支付
    机器视觉运动控制一体机应用例程|胶圈内嵌完整性检测
    【软件设计师21天-考点整理】1)计算机系统构成及硬件基础知识
  • 原文地址:https://blog.csdn.net/weixin_46787337/article/details/127869395