Vue3中對(duì)數(shù)組去重的方法總結(jié)
在 Vue 3 中對(duì)數(shù)組去重,本質(zhì)上是 JavaScript 數(shù)組操作問(wèn)題。以下是幾種常用方法,結(jié)合 Vue 3 的響應(yīng)式特性實(shí)現(xiàn)數(shù)據(jù)更新:
Vue 3數(shù)組去重方法
方法 1:使用 Set(推薦)
import { ref } from 'vue';
const list = ref([1, 2, 2, 3, 3, 3]);
// 去重邏輯
const deduplicate = () => {
list.value = [...new Set(list.value)];
// 或使用 Array.from
// list.value = Array.from(new Set(list.value));
};方法 2:使用 filter
const deduplicate = () => {
list.value = list.value.filter(
(item, index) => list.value.indexOf(item) === index
);
};方法 3:使用 reduce
const deduplicate = () => {
list.value = list.value.reduce(
(unique, item) => unique.includes(item) ? unique : [...unique, item],
[]
);
};完整組件示例
<template>
<div>
<button @click="deduplicate">去重</button>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const list = ref(['apple', 'banana', 'apple', 'orange', 'banana']);
const deduplicate = () => {
// 任選一種去重方法
list.value = [...new Set(list.value)];
};
</script>對(duì)象數(shù)組去重(根據(jù)特定屬性)
const users = ref([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' } // 重復(fù)項(xiàng)
]);
const deduplicateObjects = () => {
const seen = new Map();
users.value = users.value.filter(item => {
return !seen.has(item.id) && seen.set(item.id, true);
});
};注意事項(xiàng):
- 響應(yīng)式更新:直接賦值新數(shù)組 (
list.value = [...]) 才能觸發(fā)視圖更新 - 性能考慮:大數(shù)組推薦使用
Set或Map,時(shí)間復(fù)雜度 O(n) - 對(duì)象數(shù)組:需根據(jù)唯一標(biāo)識(shí)(如 id)去重
- 原始數(shù)組保護(hù):如果需保留原數(shù)組,操作前可深拷貝:
const newList = [...new Set(originalArray)];
響應(yīng)式原理說(shuō)明:
Vue 3 使用 Proxy 實(shí)現(xiàn)響應(yīng)式,直接修改數(shù)組元素 (list.value[0] = ...) 或使用 push() 等方法可觸發(fā)更新,但去重操作需要生成新數(shù)組并整體替換才能確保視圖正確更新。
選擇方法時(shí),簡(jiǎn)單數(shù)組用 Set 最簡(jiǎn)潔,對(duì)象數(shù)組推薦用 Map 實(shí)現(xiàn)高效去重。
在Vue 3中對(duì)對(duì)象數(shù)組進(jìn)行去重(依據(jù)所有屬性值相同),可以通過(guò)以下方法實(shí)現(xiàn)。這里提供兩種常見(jiàn)方案,推薦使用基于序列化與Set去重或使用filter與findIndex的方法:
Vue 3對(duì)對(duì)象數(shù)組進(jìn)行去重的方案
方案1:使用JSON序列化與Set(簡(jiǎn)單高效,適用于扁平對(duì)象)
import { ref, watchEffect } from 'vue';
const originalArray = ref([
{ id: 1, name: 'Alice', age: 30 },
{ id: 2, name: 'Bob', age: 25 },
{ id: 1, name: 'Alice', age: 30 }, // 重復(fù)項(xiàng)
]);
// 去重邏輯
const deduplicatedArray = ref([]);
watchEffect(() => {
const seen = new Set();
deduplicatedArray.value = originalArray.value.filter(obj => {
// 序列化對(duì)象(按鍵排序避免屬性順序不同導(dǎo)致的誤判)
const serialized = JSON.stringify(obj, Object.keys(obj).sort());
return seen.has(serialized) ? false : seen.add(serialized);
});
});
console.log(deduplicatedArray.value);
// 輸出: [{id:1, name:'Alice', age:30}, {id:2, name:'Bob', age:25}]說(shuō)明:
- 使用
JSON.stringify將對(duì)象轉(zhuǎn)換為字符串,并通過(guò)Object.keys().sort()統(tǒng)一屬性順序。 - 利用
Set檢測(cè)重復(fù)的序列化字符串,過(guò)濾重復(fù)項(xiàng)。
方案2:使用filter與自定義比較函數(shù)(支持嵌套對(duì)象,但性能較低)
import { ref, watchEffect } from 'vue';
// 深度比較兩個(gè)對(duì)象是否相等
const isEqual = (obj1, obj2) => {
const keys1 = Object.keys(obj1), keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
return keys1.every(key => {
const v1 = obj1[key], v2 = obj2[key];
if (typeof v1 === 'object' && v1 !== null && typeof v2 === 'object' && v2 !== null) {
return isEqual(v1, v2); // 遞歸比較嵌套對(duì)象
}
return v1 === v2;
});
};
const originalArray = ref([...]); // 原始數(shù)組
const deduplicatedArray = ref([]);
watchEffect(() => {
deduplicatedArray.value = originalArray.value.filter((obj, index, arr) => {
return index === arr.findIndex(item => isEqual(item, obj));
});
});說(shuō)明:
- 自定義
isEqual函數(shù)遞歸比較對(duì)象所有屬性(包括嵌套)。 - 通過(guò)
findIndex找到第一個(gè)匹配項(xiàng),保留首次出現(xiàn)的對(duì)象。
方案3:使用Vue 3的響應(yīng)式工具(組合式函數(shù)封裝)
import { ref, computed } from 'vue';
// 封裝為可復(fù)用的組合式函數(shù)
export function useDeduplicateArray(array) {
return computed(() => {
const seen = new Set();
return array.value.filter(obj => {
const serialized = JSON.stringify(obj, Object.keys(obj).sort());
return seen.has(serialized) ? false : seen.add(serialized);
});
});
}
// 在組件中使用
const originalArray = ref([...]);
const deduplicatedArray = useDeduplicateArray(originalArray);注意事項(xiàng):
序列化方法的局限性:JSON.stringify會(huì)忽略函數(shù)、undefined和循環(huán)引用,僅適用于可序列化數(shù)據(jù)。
性能考慮:
大數(shù)據(jù)量時(shí)推薦使用方案1(Set+序列化),避免嵌套循環(huán)(方案2的findIndex時(shí)間復(fù)雜度為O(n²))。
響應(yīng)式處理:
使用watchEffect或computed確保響應(yīng)式數(shù)據(jù)變化時(shí)自動(dòng)更新去重結(jié)果。
根據(jù)實(shí)際需求選擇合適方案,扁平對(duì)象推薦方案1,嵌套對(duì)象可考慮方案2或使用第三方庫(kù)(如lodash.isEqual)。
數(shù)組去重工具:arrayDeduplicateUtils.ts
import { isEqual } from "lodash-es";
/**
* 簡(jiǎn)單數(shù)組去重
* @param array 簡(jiǎn)單數(shù)組,如:["a", "b", "c", "b", "a"]、[1, 2, 3, 2, 1]
* @returns 去重的簡(jiǎn)單數(shù)組,如:["a", "b", "c"]、[1, 2, 3]
*/
export const deduplicateSimpleArray = (array: string[] | number[]) => {
// 方法1:使用 Array.from + Set
// return Array.from(new Set(array as any)) as string[] | number[];
// 方法2:使用 擴(kuò)展運(yùn)算符 ... + Set
if (array.length === 0) {
return [];
}
// 判斷數(shù)組的第一個(gè)元素是否為字符串類型
if (typeof array[0] === "string") {
return [...new Set(array as string[])];
} else {
return [...new Set(array as number[])];
}
};
/**
* 對(duì)象數(shù)組去重,通過(guò)主鍵值去重,使用 Map
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }]
*/
export const deduplicateObjectArrayByKey = (array: any[], key: string) => {
const seen = new Map();
return array.filter((item) => (seen.has(item[key]) ? false : seen.set(item[key], true)));
};
/**
* 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 JSON 序列化與 Set(適用扁平對(duì)象,簡(jiǎn)單高效)
* 1、使用 JSON.stringify 將對(duì)象轉(zhuǎn)換為字符串,并通過(guò) Object.keys().sort() 統(tǒng)一屬性順序。
* 2、使用 Set 檢測(cè)重復(fù)的序列化字符串,過(guò)濾重復(fù)項(xiàng)。
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 2, name: 'Bob', age: 35 }]
*/
export const deduplicateObjectArray = (array: any[]) => {
const seen = new Set();
return array.filter((item) => {
// 序列化對(duì)象(按鍵排序避免屬性順序不同導(dǎo)致的誤判)
const serialized = JSON.stringify(item, Object.keys(item).sort());
return seen.has(serialized) ? false : seen.add(serialized);
});
};
/**
* 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 filter、findIndex 與 lodash-es.isEqual(支持嵌套對(duì)象,性能較低)
* 1、使用 lodash-es.isEqual 深度比較兩個(gè)對(duì)象是否相等。
* 2、使用 findIndex 找到第一個(gè)匹配項(xiàng),保留首次出現(xiàn)的對(duì)象。
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 2, name: 'Bob', age: 35 }]
*/
export const deduplicateObjectArrayOfNested = (array: any[]) => {
return array.filter((item, index, arr) => {
return index === arr.findIndex((item2) => isEqual(item2, item));
});
};數(shù)組去重組合式函數(shù) hook:useArrayDeduplicate.ts
import {
deduplicateObjectArray,
deduplicateObjectArrayByKey,
deduplicateObjectArrayOfNested,
deduplicateSimpleArray
} from "@/utils/arrayDeduplicateUtils";
import { computed } from "vue";
/**
* 數(shù)組去重,組合式函數(shù) hook
*/
export const useArrayDeduplicate = () => {
/**
* 簡(jiǎn)單數(shù)組去重
* @param array 簡(jiǎn)單數(shù)組,如:["a", "b", "c", "b", "a"]、[1, 2, 3, 2, 1]
* @returns 去重的簡(jiǎn)單數(shù)組,如:["a", "b", "c"]、[1, 2, 3]
*/
const deduplicateSimpleArrayHook = (array: string[] | number[]) => {
return computed(() => {
return deduplicateSimpleArray(array);
});
};
/**
* 對(duì)象數(shù)組去重,通過(guò)主鍵值去重,使用 Map
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }]
*/
const deduplicateObjectArrayByKeyHook = (array: any[], key: string) => {
return computed(() => {
return deduplicateObjectArrayByKey(array, key);
});
};
/**
* 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 JSON 序列化與 Set(適用扁平對(duì)象,簡(jiǎn)單高效)
* 1、使用 JSON.stringify 將對(duì)象轉(zhuǎn)換為字符串,并通過(guò) Object.keys().sort() 統(tǒng)一屬性順序。
* 2、使用 Set 檢測(cè)重復(fù)的序列化字符串,過(guò)濾重復(fù)項(xiàng)。
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 2, name: 'Bob', age: 35 }]
*/
const deduplicateObjectArrayHook = (array: any[]) => {
return computed(() => {
return deduplicateObjectArray(array);
});
};
/**
* 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 filter、findIndex 與 lodash-es.isEqual(支持嵌套對(duì)象,性能較低)
* 1、使用 lodash-es.isEqual 深度比較兩個(gè)對(duì)象是否相等。
* 2、使用 findIndex 找到第一個(gè)匹配項(xiàng),保留首次出現(xiàn)的對(duì)象。
* @param array 對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 35 }]
* @returns 去重的對(duì)象數(shù)組,如:[{ id: 1, name: 'Tom', age: 30 }, { id: 2, name: 'Bob', age: 25 }, { id: 2, name: 'Bob', age: 35 }]
*/
const deduplicateObjectArrayOfNestedHook = (array: any[]) => {
return computed(() => {
return deduplicateObjectArrayOfNested(array);
});
};
return {
/** 簡(jiǎn)單數(shù)組去重 */
deduplicateSimpleArrayHook,
/** 對(duì)象數(shù)組去重,通過(guò)主鍵值去重,使用 Map */
deduplicateObjectArrayByKeyHook,
/** 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 JSON 序列化與 Set(簡(jiǎn)單高效,適用于扁平對(duì)象) */
deduplicateObjectArrayHook,
/** 對(duì)象數(shù)組去重,通過(guò)對(duì)象所有屬性值都相同去重,使用 filter、findIndex 與 lodash-es.isEqual(支持嵌套對(duì)象,性能較低) */
deduplicateObjectArrayOfNestedHook
};
};以上就是Vue3中對(duì)數(shù)組去重的方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue3數(shù)組去重的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue elementui表格獲取某行數(shù)據(jù)(slot-scope和selection-change方法使用)
這篇文章主要介紹了vue elementui表格獲取某行數(shù)據(jù)(slot-scope和selection-change方法使用),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
詳解Vue內(nèi)部怎樣處理props選項(xiàng)的多種寫法
這篇文章主要介紹了詳解Vue內(nèi)部怎樣處理props選項(xiàng)的多種寫法,詳細(xì)的介紹了props的使用的寫法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
vxe-table?實(shí)現(xiàn)?excel?選擇一個(gè)單元格拖拽自動(dòng)復(fù)制新的單元格(示例代碼)
vxe-table是一款強(qiáng)大的表格組件,支持Excel風(fēng)格的操作,通過(guò)鼠標(biāo)右下角的擴(kuò)展按鈕,用戶可以拖拽選擇單元格并自動(dòng)復(fù)制內(nèi)容到擴(kuò)展區(qū)域的所有單元格中,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-01-01
vue項(xiàng)目中使用crypto-js實(shí)現(xiàn)加密解密方式
這篇文章主要介紹了vue項(xiàng)目中使用crypto-js實(shí)現(xiàn)加密解密方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
解決Vue.js應(yīng)用回退或刷新界面時(shí)提示用戶保存修改問(wèn)題
這篇文章主要介紹了Vue.js應(yīng)用回退或刷新界面時(shí)提示用戶保存修改問(wèn)題,本文通過(guò)兩種手段防止運(yùn)營(yíng)編輯時(shí)丟失數(shù)據(jù),具體內(nèi)容詳情,感興趣的朋友跟隨小編一起看看吧2019-11-11
vue實(shí)現(xiàn)折疊展開(kāi)收縮動(dòng)畫(huà)效果
這篇文章主要介紹了vue實(shí)現(xiàn)折疊展開(kāi)收縮動(dòng)畫(huà),通過(guò)scrollHeight實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2023-11-11
關(guān)于Vue.nextTick()的正確使用方法淺析
最近在項(xiàng)目中遇到了一個(gè)需求,我們通過(guò)Vue.nextTick()來(lái)解決這一需求,但發(fā)現(xiàn)網(wǎng)上這方面的資料較少,所以自己來(lái)總結(jié)下,下面這篇文章主要給大家介紹了關(guān)于Vue.nextTick()正確使用方法的相關(guān)資料,需要的朋友可以參考下。2017-08-08

