ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

VueUse useArrayUnique 详解:响应式数组去重组合式函数的实现与实战

2026/10/5 2:10:14 拓冰建站 浏览量
VueUse useArrayUnique 详解:响应式数组去重组合式函数的实现与实战 前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载useArrayUnique是 VueUse 在vueuse/core中提供的数组类组合式函数之一它把数组去重unique逻辑封装进 Vue 的响应式系统只要传入的数组或数组元素发生变化去重结果就会自动重新计算。本文将以 skills/vueuse-functions/references/useArrayUnique.md 为核心骨架结合仓库中该函数的真实源码、测试用例与导出入口全面讲解其用法、参数语义、实现原理与适用边界读完即可在 Vue 3 / Nuxt 3 项目中直接落地使用。一、为什么需要响应式去重普通 JavaScript 去重很简单但把去重放进 Vue 组合式 API 的世界里需求就变成了三个层次的响应式数组本身可能是 refconst list ref([1, 2, 2, 3])当list.value被重新赋值时要重新去重数组元素可能各自是 refconst list [ref(0), ref(1), ref(1)]当某个ref的值变化时要重新去重数组可能是 reactive 对象const list reactive([...])执行push、splice等操作后要自动反映到结果。useArrayUnique同时覆盖这三种形态返回一个ComputedRefT[]。从源码结构看它属于 packages/shared/useArrayUnique/index.ts通过 packages/shared/index.ts 的export * from ./useArrayUnique统一导出到vueuse/core入口并在 skills/vueuse-functions/SKILL.md 的 Array 分类中被标记为AUTO调用级别——也就是说只要符合响应式数组去重的需求就可以直接使用而无需额外声明。二、三种基础用法2.1 使用多个 ref 组成的数组这是useArrayUnique最典型的场景数组里的每个元素都是独立的ref它们各自随时可能变化import { useArrayUnique } from vueuse/core const item1 ref(0) const item2 ref(1) const item3 ref(1) const item4 ref(2) const item5 ref(3) const list [item1, item2, item3, item4, item5] const result useArrayUnique(list) // result.value: [0, 1, 2, 3] item5.value 1 // result.value: [0, 1, 2]初始去重结果为[0, 1, 2, 3]重复的1只保留一个当item5的值从3变为1后数组中出现了三个1结果自动收缩为[0, 1, 2]——整个更新过程无需手动调用任何函数全部由组合式函数的响应式依赖自动驱动。2.2 使用 reactive 数组直接传入一个reactive数组后续对数组的增删改同样会触发结果更新import { useArrayUnique } from vueuse/core const list reactive([1, 2, 2, 3]) const result useArrayUnique(list) // result.value: [1, 2, 3] list.push(1) // result.value: [1, 2, 3]push(1)之后数组中1的计数变为 2但由于1已经存在于结果中去重结果维持[1, 2, 3]不变。值得注意的是result与list是单向派生关系修改result.value不会回写到原始数组。2.3 使用自定义比较函数默认去重基于严格相等语义对于对象数组尤其是同id不同实例的对象需要传入自定义比较函数compareFn。比较函数签名与Array.prototype.some的回调类似接收三个参数import { useArrayUnique } from vueuse/core const list reactive([ { id: 1, name: foo }, { id: 2, name: bar }, { id: 1, name: baz }, ]) const result useArrayUnique(list, (a, b) a.id b.id) // result.value: [{ id: 1, name: foo }, { id: 2, name: bar }] list.push({ id: 1, name: qux }) // result.value: [{ id: 1, name: foo }, { id: 2, name: bar }]{ id: 1, name: baz }与{ id: 1, name: foo }因id相同而被判定为重复只保留先出现的元素{ id: 1, name: foo }后续再push一个id: 1的新对象也不会影响结果。三、参数与返回值类型声明逐项拆解useArrayUnique的完整类型声明如下与 packages/shared/useArrayUnique/index.ts 中的声明一致export type UseArrayUniqueReturnT any ComputedRefT[] export declare function useArrayUniqueT( list: MaybeRefOrGetterMaybeRefOrGetterT[], compareFn?: (a: T, b: T, array: T[]) boolean, ): UseArrayUniqueReturnT对每个参数逐一说明项类型说明listMaybeRefOrGetterMaybeRefOrGetterT[]被去重的数组来源。MaybeRefOrGetter意味着它可以是原始数组、ref包裹的数组或返回数组的 getter 函数同时数组内部的每个元素也可以是 ref 或 getter形成双重解包compareFn(a, b, array) boolean可选的自定义相等判定函数。a是候选新元素b是已收入结果中的元素array是完整解析后的数组。省略时使用默认去重逻辑返回值ComputedRefT[]一个计算属性 ref通过.value读取去重后的数组读取时自动追踪全部依赖类型参数T支持泛型推断传入reactive([{ id: 1 }, ...])时返回值的类型会自动推断为ComputedRef{ id: number }[]无需手动标注。四、源码级实现原理useArrayUnique的实现非常精简核心逻辑全部集中在 packages/shared/useArrayUnique/index.ts 中仅 30 余行function uniqT(array: T[]) { return Array.from(new Set(array)) } function uniqueElementsByT( array: T[], fn: (a: T, b: T, array: T[]) boolean, ) { return array.reduceT[]((acc, v) { if (!acc.some(x fn(v, x, array))) acc.push(v) return acc }, []) } export function useArrayUniqueT( list: MaybeRefOrGetterMaybeRefOrGetterT[], compareFn?: (a: T, b: T, array: T[]) boolean, ): UseArrayUniqueReturnT { return computedT[](() { const resolvedList toValue(list).map(element toValue(element)) return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList) }) }这里有四个值得深入理解的设计点4.1 双重toValue解包toValue(list)负责把外层的MaybeRefOrGetterref 数组或 getter解析为普通数组随后的.map(element toValue(element))再把数组中的每一个元素逐一解包。正是这一步支撑了数组元素各自是 ref的用法——[ref(0), ref(1), ref(1)]经过双重解包后变成[0, 1, 1]再参与去重。4.2 默认路径Set去重uniq使用Array.from(new Set(array))完成去重。Set采用SameValueZero相等语义因此有两个特性值得留意NaN可以被正确去重NaN NaN在严格比较中为false但在Set语义下视为相同对象按引用比较两个内容相同但引用不同的对象会被视为不同元素这正是需要自定义compareFn的场景。4.3 自定义路径reducesome线性扫描uniqueElementsBy用Array.prototype.reduce维护一个结果累加器acc对每个新元素v通过acc.some(x fn(v, x, array))判断是否已存在等价元素只有不存在时才push。从中可以推断出两个行为约定保留首次出现的元素重复元素永远不会替换累加器中已存在的元素比较函数收到的是完整解析后的数组第三个参数array为整个输入数组可用于实现与全数组比较的更复杂判重逻辑。4.4 惰性求值与__NO_SIDE_EFFECTS__函数整体被包裹在computed中结果是惰性求值的只有读取result.value时才执行去重且依赖list及其元素变化后仅在下次读取时重算。此外函数声明上方带有__NO_SIDE_EFFECTS__注释标记这是面向打包器的纯函数提示允许 tree-shaking 工具安全地移除未使用的调用从构建层面保证vueuse/core的按需引入体积可控。五、测试用例如何验证行为仓库为useArrayUnique提供了完整的 Vitest 测试见 packages/shared/useArrayUnique/index.test.ts三个用例恰好覆盖上文三种用法it(should be defined, () { expect(useArrayUnique).toBeDefined() }) it(should work with array of refs, () { const item1 shallowRef(0) // ... const result useArrayUnique(list) expect(result.value.length).toBe(4) item5.value 2 expect(result.value.length).toBe(3) }) it(should work with ref array, () { const list deepRef([1, 2, 2, 3]) const result useArrayUnique(list) expect(result.value.length).toBe(3) list.value.push(1) expect(result.value.length).toBe(3) }) it(should work with array of reactive and custom compare function, () { // ...reactive 对象数组 自定义比较函数 expect(result.value.length).toBe(2) })测试细节值得注意测试中使用shallowRef包裹数组元素、用deepRef即ref包裹数组本身验证了元素变化触发重算与数组内容变更触发重算两条响应式链路result.value.length的断言方式也印证了返回值确实是一个需要读取.value的ComputedRef。六、适用场景与使用建议结合 skills/vueuse-functions/SKILL.md 中 Array 分类的编排useArrayUnique与useArrayDifference、useArrayFilter、useArrayFind等同属一族可以从几个角度选择性地使用它推荐场景标签/关键词列表多个独立 ref 的状态项汇总去重后渲染下拉选项、筛选项集合来自接口或用户交互的重复数据自动归一对象列表按业务主键如id、code去重配合自定义compareFn比手写Map 循环更简洁。注意事项由实现推导单向派生result是list的派生视图修改result.value不会回写原数组如需反向同步可考虑与syncRef等其他组合式函数配合对象默认按引用判重去重对象数组必须传compareFn否则每个对象都会被保留自定义比较函数的稳定语义比较函数应满足等价关系的自反、对称、传递性质且结果依赖元素首次出现顺序适合中小规模数组自定义比较路径为 O(n²) 的线性扫描some每次遍历已收集元素大规模数据数千以上建议自行用Map优化或仅在输入规模可控时使用。七、总结useArrayUnique用一个computed 双重toValue 两种去重算法Set与reduce的组合把 Vue 世界里形态各异的响应式数组统一收敛成去重视图。它既是理解 VueUse Array 系列组合式函数统一设计模式的绝佳样本也是实际项目中处理标签、选项、主键去重等需求时可以直接信任的工具。官方文档与完整源码位于 packages/shared/useArrayUnique/index.md类型定义与实现可随时对照 packages/shared/useArrayUnique/index.ts 深入阅读。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐VueUse useArrayUnique 实战指南Vue 3 响应式数组去重的完整实现与用法VueUse useArrayUnique 实战指南Vue 3 响应式数组去重的完整实现与用法 导读 useArrayUnique 是 VueUse 中用于处前端VueUse useCeil 详解响应式 Math.ceil 组合式函数的原理与实战VueUse useCeil 详解响应式 Math.ceil 组合式函数的原理与实战 useCeil 是 VueUse vueuse/math 扩展包中提供前端airi 项目中的 useArrayUnique 实战指南VueUse 响应式数组去重 Composable 的用法与原理airi 项目中的 useArrayUnique 实战指南VueUse 响应式数组去重 Composable 的用法与原理 本篇技术指南聚焦 VueUse 的AI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染上一篇AssetStudio终极指南如何轻松提取Unity游戏资源下一篇3步掌握Chrome独立代理设置突破系统级限制的专业指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考