You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3/Vuetify的v-table搜索结果出现重复条目问题求助

Vuetify v-table搜索时显示重复行问题解决

问题描述

尝试为Vuetify的v-table实现搜索功能,搜索能匹配到正确数据,但表格会显示重复行,使用Pinia存储数据,初始数据显示正常,仅搜索操作时出现重复条目。

相关代码

LogDataTable.vue

<template>
  <v-table>
    <tbody>
      <tr v-for="log in logs" :key="log.logType">
        <!-- <td>{{  log.sn }}</td> -->
        <td>{{ log.timestamp }}</td>
        <td>{{ log.logType }}</td>
        <td>{{ log.logMessage }}</td>
      </tr>
    </tbody>
  </v-table>
</template>

<script setup lang="ts">
 defineProps({
  logs: {
    type: Array,
    required: true
  }
})
</script>

Search.vue

<template>
  <v-text-field variant="outlined" density="compact" @keyup="search">
    <img :src="searchIcon" width="20" class="mr-3" />
  </v-text-field>
</template>

<script setup lang="ts">
const emit = defineEmits(['search'])
const search = (e) => {
  console.log(e.target.value)
  emit('search', e.target.value)
}
</script>

LogsPage.vue

<template>
  <div>
    <v-row>
      <v-col cols="3">
        <Search @search="searchLogs" />
      </v-col>
    </v-row>
  </div>
  <LogDataTable v-bind:logs="logs" />
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import LogDataTable from '../components/LogDataTable.vue'
import Search from '../components/Search.vue'
import { useLogsStore } from '../stores/logsStore'

const { eventLogData } = storeToRefs(useLogsStore())
const { getEventLogData } = useLogsStore()

const searchText = ref('Search')
const eventlogJson = ref([])
const eventlogJsonTmp = ref([])
const logs = ref()

const filteredData = () => {

  console.log(searchText.value)
  if (searchText.value !== '') {
    console.log('Search text is not empty>>>>>>>>>>>>>>')
    eventlogJson.value = eventlogJsonTmp.value
    logs.value = eventlogJson.value.filter(
      (eventLog) =>
        eventLog.timestamp.includes(searchText.value) ||
        eventLog.logType.includes(searchText.value) ||
        eventLog.logMessage.includes(searchText.value)
    )
    console.log('filtered log value inside if>>>>>>>>>>>>>>', logs.value)
  } else {
    logs.value = eventlogJsonTmp.value
    console.log('log value inside else>>>>>>>>>>>>>>', logs.value)
  }
}

const getJson = () => {
 /******  Some manipulations on the api data to create json ******/
        eventlogJson.value.push({
          timestamp: timestamp,
          logType: logType,
          logMessage: logMessage
        })
        console.log('logJson', eventlogJson.value)
        eventlogJsonTmp.value = eventlogJson.value
      }
    }
  }

  logs.value = eventlogJson.value
  console.log('logssssssssssss>>>>>>>>>>>>', logs.value)
 
}

const searchLogs = (search) => {
  searchText.value = search
  filteredData()
}

const displayData = async () => {
  await getEventLogData()
  getJson()
}

onMounted(() => {
  displayData()
})
</script>

问题原因

  1. v-for的key不唯一:在LogDataTable.vue中,v-for使用log.logType作为key,如果存在多条日志的logType相同,Vue的虚拟DOM无法准确区分每个列表项,过滤后重新渲染时会出现重复行。
  2. 数组引用赋值逻辑冗余:eventlogJson.value = eventlogJsonTmp.value是引用赋值,两者指向同一个数组对象,虽不直接导致重复,但会让代码逻辑混乱,增加意外出错的概率。
  3. 初始搜索文本非空:searchText初始值为'Search',可能在初始加载时触发不必要的过滤逻辑,干扰数据初始化流程。

解决方案

1. 使用唯一key

修改LogDataTable.vue中的v-for,确保每个列表项的key唯一:

  • 如果日志本身有唯一字段(比如注释掉的sn),直接使用该字段:
<tr v-for="log in logs" :key="log.sn">
  • 如果没有唯一字段,在getJson函数中为每个日志对象添加唯一ID:
// 在getJson的push操作中添加id字段
eventlogJson.value.push({
  id: Date.now() + Math.random(), // 生成唯一标识
  timestamp: timestamp,
  logType: logType,
  logMessage: logMessage
})

然后在模板中使用:

<tr v-for="log in logs" :key="log.id">

2. 简化过滤逻辑

修改filteredData函数,直接使用备份的原始数据eventlogJsonTmp进行过滤,避免不必要的数组赋值:

const filteredData = () => {
  if (searchText.value.trim() !== '') {
    logs.value = eventlogJsonTmp.value.filter(
      (eventLog) =>
        eventLog.timestamp.includes(searchText.value) ||
        eventLog.logType.includes(searchText.value) ||
        eventLog.logMessage.includes(searchText.value)
    )
  } else {
    logs.value = [...eventlogJsonTmp.value] // 浅拷贝避免引用问题
  }
}

3. 修正初始搜索文本

将searchText的初始值改为空字符串,避免初始状态下触发过滤:

const searchText = ref('')

内容的提问来源于stack exchange,提问作者Divya Bharathi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:28:11