ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VueUse useArrayDifference 实战指南:响应式数组差集、自定义比较与对称差集

VueUse useArrayDifference 实战指南:响应式数组差集、自定义比较与对称差集 前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载useArrayDifference是 VueUse 中用于响应式求两个数组差集的组合式函数它把集合论中的**相对补集A \ B与对称差集A △ B**运算带进了 Vue 3 的响应式世界只要传入的数组是 ref、reactive 数组或 getter 函数结果就会自动跟随数据变化而更新。本文将以官方文档 packages/shared/useArrayDifference/index.md 为骨架结合其源码实现 index.ts 与测试用例 index.test.ts完整讲解它的三种调用形态、symmetric选项的底层机制以及它在 VueUse 数组工具家族中的定位读完后你可以在自己的项目中直接落地使用。一、函数签名与核心概念useArrayDifference是一个惰性计算的组合式函数它本身不执行差集运算而是返回一个ComputedRefT[]只有当你访问.value时才会真正计算结果并在依赖的数组变化时自动重新计算。参数总览参数类型必填说明listMaybeRefOrGetterT[]是主数组集合 A可以传 ref、普通数组或返回数组的 getter 函数valuesMaybeRefOrGetterT[]是被比较的数组集合 B同样支持 ref / 普通数组 / getterkey形态一keyof T否指定按对象哪个属性比较等价于compareFn (a, b) a[key] b[key]compareFn形态二(value: T, othVal: T) boolean否自定义比较函数返回true表示两个元素相等optionsUseArrayDifferenceOptions否配置对象目前仅含symmetric选项UseArrayDifferenceOptions的定义在 index.ts 中export interface UseArrayDifferenceOptions { /** * Returns asymmetric difference * see https://en.wikipedia.org/wiki/Symmetric_difference * default false */ symmetric?: boolean }返回值类型为UseArrayDifferenceReturnT ComputedRefT[]见 index.ts。两种差集语义相对补集Asymmetric Difference默认行为即A \ B只包含属于 A 但不属于 B的元素数学上称为 B 在 A 中的相对补集。对称差集Symmetric Difference传入{ symmetric: true }后得到A △ B即只属于 A 或只属于 B 的元素并集等价于(A \ B) ∪ (B \ A)。这两者也是官方文档开篇就点明的核心语义index.md。二、基础用法与响应式数组配合最直接的使用方式是传入两个 ref 数组官方文档给出了一个完整的响应式示例index.mdimport { useArrayDifference } from vueuse/core const list1 ref([0, 1, 2, 3, 4, 5]) const list2 ref([4, 5, 6]) const result useArrayDifference(list1, list2) // result.value: [0, 1, 2, 3] list2.value [0, 1, 2] // result.value: [3, 4, 5]这里有两个值得注意的细节结果是响应式的result.value在list2被整体重新赋值后自动从[0, 1, 2, 3]变为[3, 4, 5]这正是computed的特性——useArrayDifference内部使用toValue()读取 ref 的最新值并把这些读取包装在computed中建立依赖追踪。保持原数组顺序与元素形态结果来自Array.prototype.filter因此输出顺序与list1一致且保留的是list1中的原引用而不是拷贝。测试用例 index.test.ts 验证了这一行为包括把list1也改掉后结果变为空数组的场景const list1 deepRef([1, 2, 3, 4, 5]) const list2 deepRef([4, 5, 6]) const result useArrayDifference(list1, list2) expect(result.value).toEqual([1, 2, 3]) list2.value [1, 2, 3] expect(result.value).toEqual([4, 5]) list1.value [1, 2, 3] expect(result.value).toEqual([])三、自定义比较函数处理对象数组当数组元素是对象时默认的严格相等比较无法正确工作此时需要传入第三个参数——自定义比较函数。官方文档示例index.mdimport { useArrayDifference } from vueuse/core const list1 ref([{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]) const list2 ref([{ id: 4 }, { id: 5 }, { id: 6 }]) const result useArrayDifference(list1, list2, (value, othVal) value.id othVal.id) // result.value: [{ id: 1 }, { id: 2 }, { id: 3 }]比较函数compareFn(value, othVal)的语义返回true表示两个元素视为相等。从源码看index.ts计算逻辑是const diff1 computed(() toValue(list).filter(x toValue(values).findIndex(y compareFn(x, y)) -1, ), )也就是说list1中每个元素x只要在list2里找不到任何一个与之相等的元素findIndex返回-1就保留在差集结果中。如果不传比较函数默认使用严格相等比较index.tsfunction defaultComparatorT(value: T, othVal: T) { return value othVal }因此对于基础类型数字、字符串数组直接省略第三参数即可只有对象、NaN等无法通过精确比较的场景才需要自定义compareFn。四、按键名比较更简洁的字符串重载对于按对象某个属性比较这一高频场景useArrayDifference还提供了更简洁的重载第三参数直接传属性名字符串。对应的类型签名在 index.tsexport function useArrayDifferenceT( list: MaybeRefOrGetterT[], values: MaybeRefOrGetterT[], key?: keyof T, options?: UseArrayDifferenceOptions, ): UseArrayDifferenceReturnT export function useArrayDifferenceT( list: MaybeRefOrGetterT[], values: MaybeRefOrGetterT[], compareFn?: (value: T, othVal: T) boolean, options?: UseArrayDifferenceOptions, ): UseArrayDifferenceReturnT当第三参数是字符串时实现会把key展开为一个比较函数index.tsif (typeof compareFn string) { const key compareFn as keyof T compareFn (value: T, othVal: T) value[key] othVal[key] }用法示例const list1 ref([{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]) const list2 ref([{ id: 3 }, { id: 4 }, { id: 5 }]) const result useArrayDifference(list1, list2, id) // result.value: [{ id: 1 }, { id: 2 }]这与显式写(value, othVal) value.id othVal.id完全等价。测试用例 index.test.ts 覆盖了该重载并验证了数组变更后结果同步更新的行为。五、对称差集开启symmetric选项如果业务需要的是只属于 A 或只属于 B 的元素例如同步两份数据时找出两侧各自独有的记录应使用对称差集。官方文档示例index.mdimport { useArrayDifference } from vueuse/core const list1 ref([{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]) const list2 ref([{ id: 4 }, { id: 5 }, { id: 6 }]) const result useArrayDifference( list1, list2, (value, othVal) value.id othVal.id, { symmetric: true }, ) // result.value: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 6 }]注意结果顺序先输出A \ B[{ id: 1 }, { id: 2 }, { id: 3 }]再拼接B \ A[{ id: 6 }]最终[{ id: 1 }, { id: 2 }, { id: 3 }, { id: 6 }]。从源码看对称差集的实现index.ts它实际计算了两个方向的差集再合并if (symmetric) { const diff2 computed(() toValue(values).filter(x toValue(list).findIndex(y compareFn(x, y)) -1, ), ) return computed(() symmetric ? [...toValue(diff1), ...toValue(diff2)] : toValue(diff1)) } else { return diff1 }两个方向都保持各自原数组的顺序diff1来自list1的过滤结果diff2来自list2的过滤结果。测试用例 index.test.ts 对symmetric与 key 形态、compareFn 形态的组合均做了验证包括两个数组完全一致时结果为空、两个数组互不相交时结果为两者并集等边界场景。六、响应式原理剖析toValuecomputed的组合理解了用法之后值得深入看一下它的响应式内核。整个函数的实现非常精简index.ts关键点有三个1. 统一解包MaybeRefOrGetter参数类型MaybeRefOrGetterT[]意味着你既可以传ref([1, 2, 3])也可以传普通数组[1, 2, 3]甚至传一个返回数组的函数const result useArrayDifference(() [1, 2, 3], list2)实现内部统一通过 Vue 的toValue()解包index.ts这也是 Vue 3.3 组合式 API 的标准做法。由于toValue是在computed的 getter 内调用的任何 ref 依赖都会被自动追踪——这就是响应式的来源。2. 惰性计算与依赖追踪函数返回的是ComputedRef差集运算只有在读取.value时才执行。只要list1或list2指向的 ref 发生变更下一次读取时就会基于最新值重新计算。函数声明上的__NO_SIDE_EFFECTS__注解index.ts也表明它不会产生任何副作用可以被安全地摇树tree-shaking与任意调用。3. 相等判定的语义边界由于使用findIndex查找是否存在相等元素useArrayDifference处理的是元素级去重视角下的差集而不是下标对齐的位置差。例如list1 [1, 2, 3]、list2 [3, 4, 5]结果为[1, 2]即使元素在数组中的位置不同只要相等由compareFn决定就被排除。这也是它与filter、includes等原生 API 组合行为的天然差异使用时需留意重复元素场景如list1中有两个1而list2中有一个1则结果中仍保留一个1因为findIndex只判断是否存在。七、在 VueUse 数组工具家族中的位置useArrayDifference属于 VueUse 的 shared 包并被统一从 packages/shared/index.ts 导出export * from ./useArrayDifference最终通过vueuse/core提供给所有使用者因此文档中的导入语句import { useArrayDifference } from vueuse/core是标准写法。它与 shared 包中的其他数组工具共同构成一套完整的响应式数组操作能力这些函数全部接受MaybeRefOrGetterT[]并返回响应式结果全部列于 packages/shared/index.ts组合式函数对应原生能力说明useArrayDifference集合差集本文主角A \ B 或 A △ BuseArrayEveryArray.every是否所有元素满足条件useArrayFilterArray.filter响应式过滤useArrayFind/useArrayFindIndex/useArrayFindLastArray.find系列响应式查找元素 / 下标 / 最后一个匹配useArrayIncludesArray.includes响应式包含判断index.mduseArrayJoinArray.join响应式拼接useArrayMapArray.map响应式映射useArrayReduceArray.reduce响应式归约useArraySomeArray.some是否存在满足条件的元素useArrayUnique去重响应式数组去重在数据对比、表单校验、标签同步、购物车合并去重等场景中useArrayDifference往往与useArrayUnique、useArrayIncludes搭配使用可以完全摆脱手写watch 手动计算的状态同步代码。八、安装与快速上手useArrayDifference随vueuse/core发布安装后即可直接使用npm i vueuse/core # 或 pnpm add vueuse/core / yarn add vueuse/core然后按需引入即可无需额外注册import { useArrayDifference } from vueuse/core const result useArrayDifference( ref([{ id: 1 }, { id: 2 }]), ref([{ id: 2 }, { id: 3 }]), id, { symmetric: true }, ) // result.value: [{ id: 1 }, { id: 3 }]由于导出的是纯 ESM 组合式函数且带__NO_SIDE_EFFECTS__标记主流打包器都能对它做 tree-shaking只把用到的函数打进产物。若你想亲自验证本文所有行为可以直接查看并运行仓库中的测试文件 index.test.ts它用 Vitest 完整覆盖了基础差集、compareFn、key 形态以及两种 symmetric 组合共 5 组断言场景。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐Ryujinx 模拟器使用指南如何构建、启动 Switch 模拟器并解决常见报错Ryujinx 模拟器使用指南如何构建、启动 Switch 模拟器并解决常见报错 Ryujinx 是一款用 C 编写的开源 Nintendo Switch 模硬件仿真图形学es-toolkit 的 xorWith用自定义比较函数计算数组对称差集的完整指南es toolkit 的 xorWith用自定义比较函数计算数组对称差集的完整指南 xorWith 是 es toolkit 数组模块中用于计算 对称差集s前端后端rui多平台开发指南如何用同一套代码部署到桌面和移动端rui多平台开发指南如何用同一套代码部署到桌面和移动端 rui是一款基于Rust的声明式UI库它让开发者能够使用同一套代码轻松构建跨桌面和移动端的应用程序。前端后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表