ARTICLE DETAIL

资讯详情

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

airi 项目实战:用 @vueuse/rxjs 的 from 与 fromEvent 打通 Vue 响应式与 RxJS 流

airi 项目实战:用 @vueuse/rxjs 的 from 与 fromEvent 打通 Vue 响应式与 RxJS 流 airi 项目实战用 vueuse/rxjs 的 from 与 fromEvent 打通 Vue 响应式与 RxJS 流【免费下载链接】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-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi本篇指南以.agents/skills/vueuse-functions/references/from.md文档为核心系统讲解vueuse/rxjs中from、fromEvent两个桥接函数它们让 RxJS 的from()/fromEvent()可以直接接收 Vue 的ref从而把某个 ref 每次变化都发射一个值、以及某个可能尚未挂载的DOM 元素事件流无缝接入 RxJS 管道。读完你能够独立搭建「RxJS 定时流 Vue ref 计数 点击停止」这类流式交互并理解WatchOptions、MaybeRef等类型在其中的作用。该技能文档位于 airi 仓库的 vueuse-functions 技能库中其RxJS分类下同时收录了 from、toObserver、useSubscription 等配套函数可互为参照阅读。为什么要包装 RxJSVue 世界与流式世界的鸿沟RxJS 的核心抽象是Observable——一种随时间推流的冷热数据源Vue 3 的核心抽象则是ref/reactive——一种被依赖追踪的响应式容器。两者都擅长表达值随时间变化但原生 API 并不能互相消费RxJS 的from()只能接收数组、Promise、可迭代对象、类 Observable 等ObservableInput不认 Vue 的refRxJS 的fromEvent()期望第一个参数是一个真实存在的 DOM 元素而 Vue 组件里通过模板引用拿到的元素在mounted之前是null原生调用极易产生时序问题。vueuse/rxjs的from/fromEvent正是为解决这两处断层而生的包装层。从该技能库的 SKILL 表格可以看到这类RxJS函数的调用规则被标记为EXTERNAL——即只有当项目真正安装了rxjs与vueuse/rxjs时才使用。airi 仓库本身大量使用 RxJS 处理事件流例如 apps/stage-web/src/pages/devtools/use-magic-keys.vue、apps/stage-pocket/src/pages/devtools/use-magic-keys.vue 等页面仓库根级 pnpm-lock.yaml 中锁定的是rxjs7.8.2因此下文示例基于 RxJS 7 的 API 形态rxjs/operators子路径导出编写。一个完整的桥接示例每秒 1、点击即停原文档的 Usage 示例覆盖了本主题最典型的一条完整链路定时器驱动 → 点击事件作为停止信号 → 与响应式计数做合并运算 → 结果写回 ref。下面逐段展开并补充注释// from.md 完整示例含逐段说明 import { from, fromEvent, toObserver, useSubscription } from vueuse/rxjs import { interval } from rxjs import { map, mapTo, takeUntil, withLatestFrom } from rxjs/operators import { shallowRef, useTemplateRef } from vue // Vue 侧状态当前累计值shallowRef 避免对大对象做深层响应化 const count shallowRef(0) // Vue 3.5 的模板引用类型为 RefHTMLElement | null const button useTemplateRef(buttonRef) useSubscription( interval(1000) // RxJS 每 1s 发射一个递增序号 .pipe( mapTo(1), // 每个序号统一映射为 1 takeUntil(fromEvent(button, click)), // 一旦按钮产生 click 事件流即终止整个管道 withLatestFrom( // 与 from(count) 流的当前值配对 from(count, { // 把 Vue ref 变成 Observable每次 count 变化发射新值 immediate: true, // 订阅时立刻发射当前值第一次配对才有初始值可用 deep: false, // 浅层监听即可 }), ), map(([curr, total]) curr total), // 每 tickcurr1 total当前 count ) .subscribe(toObserver(count)), // Observer 直接写回 ref // 组件卸载时自动调用 unsubscribe见 useSubscription 语义 )逐行理解这条管道interval(1000)产生无休止的递增整数序列takeUntil(fromEvent(button, click))是停止条件它订阅的是由ref 指向的按钮元素上的 click 事件流。文档明确说明当 ref 的值变化时例如组件挂载后元素才可用fromEvent会自动订阅新元素——这正是模板引用场景下原生fromEvent做不到的withLatestFrom(...)每次需要拿count的当前值而count是 Vue ref所以通过from(count, { immediate: true })先转成 Observable。immediate: true保证第一次就能拿到初始值否则要等count首次变化后才会有配对流首次 tick 会被丢弃最终结果通过toObserver(count)写回——它等价于手动subscribe((val) (count.value val))但更简洁且类型安全。配对的useSubscription会在组件卸载前自动调用订阅的unsubscribe其类型声明为useSubscription(subscription: Unsubscribable): void从而规避内存泄漏这正是 SKILL 文档所强调的可组合式方案优于手写样板代码的落地体现。from让 ref 成为一个随变化而发射的 Observablefrom的函数签名文档 Type Declarations 原文为export declare function fromT( value: ObservableInputT | RefT, watchOptions?: WatchOptions, ): ObservableT即它同时支持两类输入标准 RxJSObservableInput数组、Promise、可迭代对象、生成器等——此时行为退化为原版from直接把输入摊平成事件流Vueref此时内部等价于对 ref 建立 Vue 的watch每次 ref 值变化就向下游next一次新值。Watch Options 详解当以 ref 调用from时第二参数透传的是 Vue 3 的WatchOptions原文档的参数表完整罗列了三个核心选项OptionTypeDescriptionimmediatebooleanEmit the current value immediately订阅后立即发射当前值常用于给withLatestFrom/startWith之外的场景提供初始快照deepbooleanDeeply watch nested objects对嵌套对象开启深层遍历性能代价随对象规模上升能浅则浅flushpre \| post \| syncTiming of the callback flush回调刷新的时机默认同 Vue watch 的pre即组件更新前实际选用建议想要一订阅就有值统计、初始化场景设immediate: true监听对象内嵌字段的增减且需要逐层追踪设deep: true若只关心引用替换保持deep: false默认以降低开销示例中的计数器正是浅层监听即可的代表flush决定发射与组件渲染/副作用执行周期的相对顺序涉及 DOM 读写时按 Vue watch 的同样语义选择pre | post | sync。该参数设计在 VueUse 体系里是通用惯例——例如同为本仓库技能库收录的 watch 家族函数watchImmediate、watchDeep等本质上就是把这几个选项固化为函数名理解from的WatchOptions后可以触类旁通。fromEvent延迟挂载元素的事件流交给 ref 来解fromEvent的签名文档 Type Declarations 原文为export declare function fromEventT extends HTMLElement | null( value: MaybeRefT, event: string, ): ObservableEvent两个要点值得展开第一参数是MaybeRefT既可以传真实元素也可以传一个值为元素或null的 ref自动订阅逻辑由于ref初值在模板渲染前是nullfromEvent需要内部等待元素出现。文档描述为当 ref 的值变化时比如组件挂载完成后它自动对新元素建立监听。这等价于先对 ref 做一次解引用解析VueUse 中通常配合unrefElement语义再进入挂载时机判断。from.md给出的最小示例import { fromEvent, useSubscription } from vueuse/rxjs import { useTemplateRef } from vue const button useTemplateRef(buttonRef) // Will automatically subscribe when the button element becomes available useSubscription( fromEvent(button, click).subscribe(() { console.log(clicked!) }) )与之配合的模板只需声明同名引用即可无需任何手动onMounted再绑定的代码button refbuttonRefstop interval/button对比原生写法这里省去了三段样板mounted里判空、addEventListener、unmounted里removeEventListener。反过来若把完整示例里button的 ref 换成一个始终为null的 ref那么该元素事件流永远不会产生事件takeUntil永不触发——这也解释了为何停止按钮不显示时计时器仍会继续跑排查此类问题时优先检查模板 ref 是否真的绑定到了元素。实战组合toObserver、useSubscription 与定时器停止按钮from/fromEvent是纯源构造器它们通常与同一技能目录下的另外两个函数组合使用形成闭环toObservertoObserverT(value: RefT): NextObserverT把一个 ref 包装成 RxJSNextObserver所有next值自动写入ref.value是与ref 流入管道反向对称的流回写 ref出口useSubscriptionuseSubscription(subscription: Unsubscribable): void把订阅生命周期挂到当前组件作用域卸载即自动退订。由此可拼出文档示例之外一个常见变体——「暂停/继续计时器」的控制流。仅需把完整示例中的interval(1000)替换为interval(1000).pipe(takeUntil(fromEvent(pauseBtn, click)))并在useSubscription之上再叠加一层useSubscription(fromEvent(resumeBtn, click).pipe(tap(() { /* 重新启动一段新 interval 订阅 */ })))即可实现暂停/继续在 airi 这类多端 Vue 应用apps/stage-web、apps/stage-pocket、apps/stage-tamagotchi均使用vueuse/core中该模式常被用于轮询、按键连发、事件驱动型 UI 状态等需要精确控制何时开始/何时停止的交互。局限与注意事项EXTERNAL依赖按 SKILL 文档约定RxJS类函数只有在项目已安装rxjs与vueuse/rxjs时才应使用本仓库锁定的 RxJS 主版本为 7.x示例导入路径均按 RxJS 7 的rxjs/operators写法升级到 RxJS 8 前需同步核对子路径导出immediate的语义差异from(count)的immediate指订阅即刻发射一次当前值与操作符startWith效果接近但实现位置不同两者同时使用可能造成重复的初始发射需按数据流自行取舍deep监听成本深层监听会遍历整棵对象图高频更新的大对象应避免开启flush: sync会让发射与变更同步发生若管道下游有重计算需评估是否引入性能抖动事件类型收敛fromEvent第二参数是字符串event返回类型统一为ObservableEvent若需要KeyboardEvent等细分类型应在管道中用类型断言或在回调内收窄这是类型声明上的已知取舍。延伸阅读from / fromEvent 参考文档本文依据的原始文档toObserver 参考文档ref 反写回流的 Observer 转换useSubscription 参考文档自动退订的订阅封装vueuse-functions 技能库总览RxJS分类下还包含useObservable、useSubject、useExtractedObservable等更多流式工具调用规则、分类与函数矩阵均可在此总览中查阅。【免费下载链接】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-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表