☰
VueUse @vueuse/math 之 logicNot:为 ref 提供响应式 NOT 逻辑判断的完整实战指南
2026/10/3 1:52:23 网站建设 项目流程
  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载

logicNot是 VueUse 数学扩展包@vueuse/math提供的逻辑组合函数之一,其作用是对传入的 ref、普通值或 getter 函数取逻辑非(!),并返回一个类型为ComputedRef<boolean>的响应式计算结果。本文将以 logicNot 官方文档 为核心骨架,结合 源码实现 与 单元测试 深入讲解其工作原理、与whenever的经典组合用法,以及它与logicAnd、logicOr构成的完整逻辑函数家族,帮助你在 Vue 3 组合式 API 场景中精准驾驭“反向条件”的响应式编程。

一、功能定位:为 ref 而生的 NOT 条件

logicNot解决的是一类非常常见但容易写脏的 Vue 响应式需求:当某个 ref 的值由真变假(或由假变真)时,触发一段逻辑。直接写!a.value只能拿到一次性快照,无法保持响应式;而logicNot(a)返回的ComputedRef会随着a的变化持续重算,天然融入 Vue 的响应式依赖追踪体系。

在 VueUse 的官方分类中,logicNot属于@Math类别,文档 frontmatter 中声明了别名alias: not,即历史上它也曾以not命名导出(详见下文“别名与迁移”一节)。

import { whenever } from '@vueuse/core' import { logicNot } from '@vueuse/math' const a = ref(true) whenever(logicNot(a), () => { console.log('a is now falsy!') })

这是 官方文档 中的标准用法:whenever监听logicNot(a)这个 computed 值,一旦它变为 truthy(即a变为 falsy),回调便会被触发。整个链路完全由响应式系统驱动,无需手动订阅与清理。

二、安装与引入

logicNot与logicAnd、logicOr、useSum、useAverage等一起打包在@vueuse/math子包中,同时依赖@vueuse/core(示例中的whenever来自 core)。按照 packages/math/README.md 的说明安装:

npm i @vueuse/math @vueuse/core

引入方式与官方文档保持一致:

import { logicNot } from '@vueuse/math'

所有 math 工具统一从 packages/math/index.ts 的入口聚合导出,其中包含export * from './logicNot'一行,因此从包根路径导入即可,无需深链到具体目录。

三、源码剖析:computed + toValue 的极简实现

logicNot的完整实现只有短短几行,但它精准体现了 VueUse 工具函数的通用设计范式。以下为 packages/math/logicNot/index.ts 的完整源码:

import type { ComputedRef, MaybeRefOrGetter } from 'vue' import { computed, toValue } from 'vue' export function logicNot(v: MaybeRefOrGetter<any>): ComputedRef<boolean> { return computed(() => !toValue(v)) }

1. 入参类型:MaybeRefOrGetter<any>

函数唯一参数的类型是MaybeRefOrGetter<any>,这是 Vue 3.3+ 引入的宽松入参类型,它涵盖三类输入:

输入形态示例处理方式
普通值logicNot(true)toValue直接返回原值
ReflogicNot(ref(true))toValue自动解包,读取.value
Getter 函数logicNot(() => true)toValue调用函数取返回值

正因为接受“值 / ref / getter”三种形态,logicNot既可以用在静态场景(对普通布尔值取反),也可以用在动态场景(包裹响应式 ref),而调用方无需关心底层形态差异。

2. 核心机制:computed 惰性重算

返回值是computed(() => !toValue(v))。computed保证了两个关键性质:

  • 惰性求值:只有被读取时(例如被模板、watch、whenever或toValue访问)才会真正计算;
  • 依赖追踪:当v是 ref 或 getter 内部引用了响应式状态时,toValue的读取行为会被 Vue 收集为依赖,v变化时该 computed 自动失效并重算。

从源码结构看,这正是logicNot与!a.value这类手写表达式最本质的区别:前者是响应式数据流中的一等公民,后者是一次性快照。

3. 语义细节:JS 真值(truthy/falsy)而非严格布尔

!toValue(v)使用的是 JavaScript 的通用真值语义,因此它不仅处理true/false,还覆盖了所有 falsy 值。这一点被 单元测试 明确验证:

// falsy 输入 -> 返回 true expect(toValue(logicNot(shallowRef(false)))).toBe(true) expect(toValue(logicNot(shallowRef('')))).toBe(true) expect(toValue(logicNot(shallowRef(0)))).toBe(true) // truthy 输入 -> 返回 false expect(toValue(logicNot(shallowRef(true)))).toBe(false) expect(toValue(logicNot(shallowRef('foo')))).toBe(false) expect(toValue(logicNot(shallowRef(1)))).toBe(false)

测试覆盖了 ref、普通值、getter 三种输入形态,例如logicNot(() => 0)返回true、logicNot('foo')返回false。这意味着logicNot可用于判断“空字符串、数字 0、null、undefined、NaN等 falsy 状态”,而不仅仅局限于布尔标志位。

四、实战用法:与 whenever 的组合模式

logicNot最经典的搭档是 VueUse 的whenever,用于在某个 ref 变为 falsy 时执行副作用。官方示例:

import { whenever } from '@vueuse/core' import { logicNot } from '@vueuse/math' const a = ref(true) whenever(logicNot(a), () => { console.log('a is now falsy!') })

这段代码等价于手写watch(() => !a.value, cb),但语义更直白、可读性更高,而且logicNot的返回值本身就是ComputedRef<boolean>,可以直接传给watch、watchEffect、whenever等任何接受响应式数据源的 API。

典型场景一:表单校验的“反向提示”

import { logicNot } from '@vueuse/math' import { whenever } from '@vueuse/core' const email = ref('') const isValid = computed(() => /\S+@\S+\.\S+/.test(email.value)) // 邮箱从合法变为不合法时,立即提示 whenever(logicNot(isValid), () => { showError.value = true })

注意这里logicNot的入参是另一个ComputedRef,再次印证了MaybeRefOrGetter的兼容性——computed 同样属于 ref 的一种。

典型场景二:条件渲染与样式切换

const loading = ref(true) // 模板中直接使用,响应式驱动 UI // v-if="logicNot(loading)" 等价于 v-if="!loading"

不过需要说明:模板里直接用!loading即可,logicNot的价值更多体现在需要把“取反后的条件”作为值传递给其他组合式函数、watch 数据源或复用于多处时,避免重复编写!xxx.value表达式,也让逻辑命名更具可读性。

五、逻辑函数家族:logicNot / logicAnd / logicOr

logicNot并非孤立存在,它与logicAnd、logicOr共同构成 VueUse 的响应式布尔逻辑家族,三者实现高度同构。对照 logicAnd 源码 与 logicOr 源码:

// logicAnd:全部为 truthy 才返回 true export function logicAnd(...args: MaybeRefOrGetter<any>[]): ComputedRef<boolean> { return computed(() => args.every(i => toValue(i))) } // logicOr:任一为 truthy 即返回 true export function logicOr(...args: MaybeRefOrGetter<any>[]): ComputedRef<boolean> { return computed(() => args.some(i => toValue(i))) }
函数运算入参形态返回文档别名
logicNot(v)!toValue(v)单个MaybeRefOrGetterComputedRef<boolean>not
logicAnd(...args)全部 truthy可变参数MaybeRefOrGetter[]ComputedRef<boolean>and
logicOr(...args)任一 truthy可变参数MaybeRefOrGetter[]ComputedRef<boolean>or

三者均以@__NO_SIDE_EFFECTS__注解标记为无副作用纯函数(便于摇树优化与 SSR 分析),且都通过computed保持响应式。从 logicAnd 文档 和 logicOr 文档 的 frontmatter 可以看到,官方将三者用related字段互相关联,建议在需要组合布尔条件时直接混用:

import { logicAnd, logicOr, logicNot } from '@vueuse/math' import { whenever } from '@vueuse/core' const isAdmin = ref(false) const isLoggedIn = ref(true) const isBanned = ref(false) // 登录且未被封禁 且(是管理员 或 非游客) whenever( logicAnd(isLoggedIn, logicNot(isBanned), logicOr(isAdmin, logicNot(ref('guest')))), () => { /* 放行逻辑 */ }, )

logicAnd、logicOr接受可变参数列表,可直接把多个 ref 一次性传入,而logicNot负责对其中任一条件单独取反,三者组合可以构建任意复杂的响应式布尔表达式,且全程保持声明式、可读、无手动订阅。

六、别名与迁移:not → logicNot

在 packages/math/logicNot/index.ts 的末尾,保留了历史别名导出:

/** @deprecated use `logicNot` instead */ export const not = logicNot

即早期版本中该函数以not命名导出,现已被logicNot取代,not仅作为向后兼容的弃用别名保留。logicAnd、logicOr也存在对应的弃用别名and、or。因此:

  • 新代码请统一使用logicNot;
  • 若在旧代码中见到import { not } from '@vueuse/math',其行为与logicNot完全一致,但应尽快迁移;
  • 文档 frontmatter 中的alias: not正是为文档站点链接与历史引用提供的别名登记。

七、注意事项与边界

  1. 返回类型恒为ComputedRef<boolean>:即使入参是普通值(如logicNot(0)),返回值也是 computed,需要用.value、模板解包或toValue()读取,不可直接当布尔量比较。
  2. 真值语义而非严格类型:logicNot遵循 JavaScript 真值规则,''、0、null、undefined、NaN都会被取反为true。若需要严格的布尔比较,应在入参侧先做归一化(如computed(() => a.value === true))。
  3. getter 形态的响应式来源:当传入() => someRef.value > 0这类 getter 时,toValue执行函数期间读取的响应式状态会成为 computed 的依赖,同样具备响应式更新能力;但 getter 本身不应包含副作用,否则每次重算都会重复执行。
  4. 无清理负担:logicNot本身不注册任何监听器或副作用,其响应式更新完全由 Vue 的computed机制托管,组件卸载时自动回收,无需手动 dispose。

结语

logicNot是 VueUse 数学扩展包中最“小而美”的工具之一:三行核心代码,借助MaybeRefOrGetter、toValue与computed三大 Vue 原语,把“对响应式值取反”这一高频需求封装成可组合、可复用、可测试的纯函数。配合whenever做反向条件触发、与logicAnd/logicOr组合构建复杂布尔逻辑,它能让你的 Vue 3 代码在条件表达层面同样保持声明式与可读性。若想进一步验证其行为细节,可直接阅读仓库内的 源码、测试用例 以及 logicAnd、logicOr 的配套文档。

  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载

相关推荐

上一篇:GitHub_Trending/cr/create-t3-turbo无服务器数据库:DynamoDB与Firebase对比
下一篇:零知识证明商业变现终极指南:ZKP技术在10大行业的赚钱机会

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

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

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

立即咨询