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>
问题原因
- v-for的key不唯一:在
LogDataTable.vue中,v-for使用log.logType作为key,如果存在多条日志的logType相同,Vue的虚拟DOM无法准确区分每个列表项,过滤后重新渲染时会出现重复行。 - 数组引用赋值逻辑冗余:
eventlogJson.value = eventlogJsonTmp.value是引用赋值,两者指向同一个数组对象,虽不直接导致重复,但会让代码逻辑混乱,增加意外出错的概率。 - 初始搜索文本非空:
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
相关产品推荐
相关产品推荐

