深入解析 airi 项目中的 VueUse useArrayEvery:响应式 Array.every 的完整指南
2026/9/10 3:19:16 网站建设 项目流程

深入解析 airi 项目中的 VueUse useArrayEvery:响应式 Array.every 的完整指南

【免费下载链接】airi💖🧸 Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

导读

useArrayEvery是 VueUse 响应式工具集(Array 分类)中的一员,本质上是将原生Array.prototype.every包装为响应式版本:当数组或其元素发生变化时,计算结果会自动重算。在 airi 这样的 Web / macOS / Windows 跨端 Vue 3 应用中,它常用于"全部条件同时满足"类校验——例如表单整体可提交判断、性能指标全部启用校验、多包币种全部可用检查。读完本文你将掌握:useArrayEvery的两种典型调用形态(多个 ref 构成的数组、响应式数组)、完整的类型签名解读、在 airi 仓库中的实际落地场景,以及与其姊妹函数(useArraySomeuseArrayFilter等)的选型对比。


一、从 VueUse 到 airi:这个函数的项目背景

airi 是一个自托管的 AI Companion 桌面/Web 项目(Web / macOS / Windows 支持),其前端全部基于 Vue 3 构建,并通过 pnpm workspace 统一管理依赖。仓库的 pnpm-workspace.yaml 中以 catalog 方式声明了核心版本:

'@vueuse/core': ^14.4.0 '@vueuse/shared': ^14.4.0

useArrayEvery就来自@vueuse/core(同时依赖@vueuse/shared的基础类型与工具函数)。在 airi 的多个子应用与包中均直接依赖@vueuse/core,例如 apps/stage-web/package.json、apps/stage-pocket/package.json、apps/stage-tamagotchi/package.json、packages/stage-pages/package.json、packages/electron-vueuse/package.json 等,因此useArrayEvery在整个 airi 代码库中开箱即用。

此外,仓库内置的 AI 编码技能 .agents/skills/vueuse-functions/SKILL.md 将 VueUse 函数按功能分类(State、Elements、Array、Reactivity 等),其中Array 分类明确收录了useArrayEvery,描述为 "ReactiveArray.every",并标注Invocation: AUTO——即在 Vue.js / Nuxt 开发中,只要需求可映射到该函数就应优先使用,而不是手写监听逻辑。本篇文章讲解的参考文档正是该技能目录下的 .agents/skills/vueuse-functions/references/useArrayEvery.md,该文档由vendor/vueuse/skills/vueuse-functions同步而来(见 .agents/skills/vueuse-functions/SYNC.md),是标准的 VueUse 官方函数参考。

适用前提:需要 Vue 3(或以上)/ Nuxt 3(或以上)项目,并已安装@vueuse/core(airi 各前端应用均满足)。


二、核心概念:什么是"响应式 Array.every"

原生 JavaScript 的Array.prototype.every(callback)会遍历数组,当每一个元素都让回调函数返回真值时返回true,否则立即短路返回false。但它是一次性计算,数组变化后不会自动更新。

useArrayEvery把这一语义搬进 Vue 的响应式系统:它接受一个可响应的数组(数组本身可以是ref/getter,数组元素也可以是ref/getter),返回一个ComputedRef<boolean>。任何相关依赖(数组引用、元素值)发生变化时,计算结果都会自动重新求值,无需手动watch+ 赋值。

从 useArrayEvery.md 给出的类型声明可以清晰看到设计:

export type UseArrayEveryReturn = ComputedRef<boolean> export declare function useArrayEvery<T>( list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>, fn: (element: T, index: number, array: MaybeRefOrGetter<T>[]) => unknown, ): UseArrayEveryReturn

逐项解读:

  • list: MaybeRefOrGetter<MaybeRefOrGetter<T>[]>:第一层MaybeRefOrGetter表示整个数组可以是普通数组、Ref<Array>或返回数组的 getter;第二层MaybeRefOrGetter<T>表示每个元素也允许是普通值、Ref<T>或返回T的 getter。这对应文档中两种官方用法(见下文第三、四节)。
  • fn: (element, index, array) => unknown:测试回调,签名与原生Array.prototype.every一致,接收元素、下标与整个数组;返回值只需为 truthy/falsy 即可,不必是布尔值。
  • 返回值ComputedRef<boolean>:当fn对数组每一个元素都返回 truthy 时为true,否则为false;且标注了@__NO_SIDE_EFFECTS__,即该组合式函数无副作用,可安全用于 SSR/组合式函数上下文中。

实现推断:从返回类型是ComputedRef<boolean>可以看出,其内部必然基于computed构建,并在求值过程中先对传入的 list 解包(toValue),再对每个元素逐一解包后调用fnevery短路判断——这与 VueUse 中useArrayFilteruseArraySome等"响应式数组变换"家族的实现模式一致(同属 Array 分类,见 SKILL.md 中的 Array 函数表)。


三、用法一:与多个 ref 构成的数组搭配

这是文档给出的第一种官方用法,适用于元素各自是独立 ref的场景。以文档示例为基础:

import { useArrayEvery } from '@vueuse/core' const item1 = ref(0) const item2 = ref(2) const item3 = ref(4) const item4 = ref(6) const item5 = ref(8) const list = [item1, item2, item3, item4, item5] const result = useArrayEvery(list, i => i % 2 === 0) // result.value: true item1.value = 1 // result.value: false

执行过程推演:

  1. 初始时数组元素为0, 2, 4, 6, 8,全部是偶数,i % 2 === 0对每个元素都成立,因此result.value === true
  2. item1.value = 1时,数组第一项变为奇数,every语义下不再"全部通过",结果立即变为false

这种形态的关键价值在于:被追踪的依赖是元素 ref 本身,而不是数组的引用。即使list数组变量本身从未被重新赋值,只要其中任意一个ref的值改变,result都会响应式更新。


四、用法二:与响应式数组(ref array)搭配

第二种官方用法面向"整组数据都在一个 ref 数组里"的场景:

import { useArrayEvery } from '@vueuse/core' const list = ref([0, 2, 4, 6, 8]) const result = useArrayEvery(list, i => i % 2 === 0) // result.value: true list.value.push(9) // result.value: false

这里list是一个Ref<number[]>。调用push(9)之后数组包含奇数 9,result.value自动变为false。注意:Vue 3 的ref对数组的响应式是基于 Proxy 的深层响应式,因此pushsplice、下标赋值等原地变更都能被computed依赖收集捕捉到,这正是useArrayEvery能感知"数组内容变化"的底层机制。

对比两种用法可归纳出选型建议:

场景推荐形态
元素是独立的 ref,分散在不同状态中多个 ref 构成的数组(用法一)
数据天然集中在一个响应式数组中(如列表、批量配置)ref([...])响应式数组(用法二)

两种形态均无需手写watch、无需computed(() => list.value.every(...))之外的心智负担,且都保持ComputedRef<boolean>的返回值协议,可在模板中直接v-if="result"或在组合式函数中继续派生。


五、在 airi 仓库中的真实应用场景

虽然useArrayEvery本体的源码位于@vueuse/core依赖中(node_modules),但 airi 代码库中存在大量与其语义一致的"全量校验"逻辑,可以直接替换为useArrayEvery以收敛样板代码。下面两处是典型代表:

场景 A:性能指标全部启用判定

在 apps/stage-web/src/pages/devtools/performance-visualizer.vue 中,出现了对指标启用状态的批量校验:

supportedMetrics.every(metric => enabled.value[metric.key])

这里的意图是"所有支持的指标都已启用才……"。supportedMetricsenabled都是响应式来源,正是useArrayEvery(supportedMetrics, metric => enabled.value[metric.key])的天然替换点——替换后可获得ComputedRef<boolean>,并随enabled状态自动更新。

场景 B:多币种包全部可用检查

在 packages/stage-pages/src/pages/settings/flux.vue 中:

.filter(c => packages.value.every(p => c in p.currencies))

遍历候选货币,过滤出"每个包(packages)的 currencies 中都包含该货币"的项。内层packages.value.every(...)判断的正是"全部包都支持",与useArrayEvery(packages, p => c in p.currencies)语义一致。

这类"全部满足"判定在 airi 的桌面端(stage-tamagotchi)、Web 端(stage-web)、移动端(stage-pocket)乃至 stage-pages 包中普遍存在,统一收敛到useArrayEvery后,代码可读性、可维护性与响应式正确性都能得到提升。


六、选型对比:useArrayEvery 与相关函数

useArrayEvery属于 VueUse 的Array 分类。在 SKILL.md 的 Array 表中,与之相邻的函数包括useArraySomeuseArrayFilteruseArrayFinduseArrayMapuseArrayIncludesuseArrayJoinuseArrayReduceuseArrayUniqueuseArrayDifferenceuseSorted,它们全部标注为AUTO 调用。选型要点:

函数语义适用场景
useArrayEvery全部元素通过测试 →true全量条件校验(本文主题)
useArraySome任一元素通过测试 →true至少一个满足(如"存在启用中的指标")
useArrayFilter过滤出通过测试的元素保留满足条件的子集
useArrayFind返回第一个通过测试的元素查找目标项
useArrayIncludes判断是否包含指定值成员存在性判断
useArrayMap/useArrayReduce映射 / 归约派生新数组或聚合值

决策原则(来自 SKILL.md 的 When to Apply):在 Vue.js / Nuxt 开发中先检查 VueUse 是否已有对应函数;优先用组合式函数替代自造代码;Invocation 为AUTO的(如useArrayEvery)在适用时直接使用,无需征求用户额外确认。换言之:需要"全部满足"判断时,useArrayEvery就是首选答案


七、常见问题与注意事项

  1. 返回值始终是ComputedRef<boolean>:读取需.value(模板中自动解包),不要把它当作普通布尔值直接比较。
  2. 回调返回 truthy 即可fn类型为(element, index, array) => unknown,不强制返回严格boolean,与原生every一致。
  3. 对空数组的语义every对空数组天然返回true(数学上的"真空真"),useArrayEvery继承该语义,涉及空数组判定时需自行注意。
  4. 深层响应式依赖:用法二中ref([...])依赖 Vue 3 的 Proxy 深层响应式,原地修改(push/下标赋值)才会被追踪;若替换整个数组引用(list.value = [...])同样有效。
  5. 版本与运行环境:airi 当前 catalog 版本为@vueuse/core ^14.4.0(见 pnpm-workspace.yaml),该函数要求 Vue 3(或以上),适合 airi 的 Web / macOS / Windows 三端 Vue 3 工程。

小结

useArrayEvery是"把原生Array.every接入 Vue 响应式"的最短路径:一条computed语义、零样板代码、两种输入形态,返回值类型明确(ComputedRef<boolean>),并由 airi 内置的 VueUse 技能(SKILL.md)标记为 AUTO 优先调用。无论是多 ref 分散状态(用法一)还是集中式响应式数组(用法二),它都能让"全部条件同时成立"这类判断随状态自动保鲜。对照 airi 中 performance-visualizer.vue 与 flux.vue 的既有every用法,你可以快速将这类模式收敛为响应式组合式函数,让代码更简洁、更可维护。

【免费下载链接】airi💖🧸 Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询