ARTICLE DETAIL

资讯详情

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

用 XState v5 与 Vue 构建 7GUIs Counter:从状态机到组件的完整实战

用 XState v5 与 Vue 构建 7GUIs Counter:从状态机到组件的完整实战 前端后端【免费下载链接】xstateState machines, statecharts, and actors for complex logic项目地址https://gitcode.com/gh_mirrors/xs/xstate点击查看免费下载XState 是一个用于建模复杂逻辑的 JavaScript/TypeScript 库其核心理念是状态机state machines、状态图statecharts与 Actor 模型。本篇文章基于当前仓库xs/xstate中examples/7guis-1-counter-vue这一示例讲解如何用XState v5 Vue 3 TypeScript Vite构建 7GUIs7 Graphical User Interfaces 基准测试套件中的第一个任务 —— 一个仅含显示计数 递增按钮的 Counter。读完后你将掌握用setup()定义类型安全的机器、用assign内建动作更新context、用xstate/vue的useMachine()在 Vue 组件中接入状态机以及如何在本地运行和在线预览这个示例。说明仓库中该示例的依赖版本为xstate ^5.28.0、xstate/vue ^3.1.4、vue ^3.5.29、vite ^5.4.21见 examples/7guis-1-counter-vue/package.json下文所有代码均以此为准。1. 示例概览与 7GUIs 背景7GUIs 是 Eugen Kiss 提出的一组经典 GUI 基准任务用于检验不同 UI 框架/工具在典型交互场景下的表达能力Counter 是其第 1 个任务原文档在 examples/7guis-1-counter-vue/README.md 中明确了这一点。任务需求很简单显示一个数值点击按钮使其加一。本示例把它实现为一个状态机驱动的 Vue 应用文件结构如下全部位于examples/7guis-1-counter-vue/src/counterMachine.ts—— 定义 Counter 状态机业务逻辑核心src/Counter.vue—— 使用useMachine接入状态机并渲染 UI 的组件src/App.vue—— 仅负责挂载Counter的根组件src/main.ts—— Vue 应用入口src/style.css—— 7GUIs 风格的全局样式vite.config.ts、package.json、tsconfig.json等工程配置2. 用setup()定义类型安全的计数器状态机counterMachine.ts是本例的灵魂完整代码如下见 examples/7guis-1-counter-vue/src/counterMachine.tsimport { setup, assign } from xstate; export const counterMachine setup({ types: { context: {} as { count: number }, events: {} as { type: increase } } }).createMachine({ context: { count: 0 }, id: Counter, initial: ready, states: { ready: { on: { increase: { target: ready, actions: assign({ count: ({ context }) context.count 1 }) } } } } });2.1setup()XState v5 的类型安全入口XState v5 引入了setup()作为创建机器的新推荐方式。从源码看packages/core/src/setup.tssetup接受一个包含schemas、types、actors、actions、guards、delays的配置对象返回一个SetupReturn对象其上挂有createMachine、createAction、createStateConfig、extend以及assign、sendTo、raise、log、emit、spawnChild等内建动作见 packages/core/src/setup.ts。在本例中setup的types字段声明了两类类型信息context: {} as { count: number }—— 声明机器上下文中有一个count: number字段events: {} as { type: increase }—— 声明该机器唯一可接收的事件是{ type: increase }。之后调用.createMachine({ ... })生成实际机器。这种先声明类型、再定义配置的方式让后续配置中的context、on、actions等全部获得编译期类型检查比如向send传递{ type: decrease }这类未声明的事件会直接报错这正是 XState v5 强类型体验的核心。2.2context机器的可读状态context: { count: 0 }定义了机器的初始上下文。在状态机术语中context是与状态正交的可变数据与当前处于哪个状态state value共同构成快照snapshot。本例只关心计数数值因此把count放进context而状态本身仅有一个ready。2.3id与initial/statesid: Counter给机器一个稳定标识便于调试与引用initial: ready指定初始状态states定义状态集合这里只有一个ready状态其中on声明了事件到转移的映射。虽然这个例子只有单个状态、结构极简但它完整展示了状态机的基本骨架。当业务变复杂时可以在states中扩展多个状态与转移这也是 XState 处理复杂逻辑的核心优势。2.4assign更新 context 的唯一内建方式转移中的actions: assign({ count: ({ context }) context.count 1 })是理解本例的关键。assign是 XState 的内建动作built-in action专门用于不可变地更新机器的 context。从实现看packages/core/src/actions/assign.tsassign接收一个赋值器assignment可以是一个函数({ context, event }) partialContext一个属性映射对象{ count: ({ context }) context.count 1 }本例所用形式其中每个字段的值可以是函数根据当前context/event计算新值也可以是常量。在resolveAssign中packages/core/src/actions/assign.ts最终通过Object.assign({}, snapshot.context, partialUpdate)生成一份新的 context再调用cloneMachineSnapshot产出新快照 —— 也就是说assign不会就地修改旧 context而是返回不可变的新快照这与 Vue 的响应式心智模型天然契合。需要特别注意的是assign是声明式动作不能把它直接写进普通自定义动作里命令式调用开发模式下会给出警告见 packages/core/src/actions/assign.ts。2.5 一次点击背后的完整转移语义当收到increase事件时状态机执行一次转移事件匹配ready状态的on.increasetarget: ready表明转移目标仍是ready状态即自转移self-transition这是计数器的典型写法 —— 我们不离开当前状态只更新数据actions中的assign被解析执行count从context.count加一状态机发出新的快照xstate/vue的订阅机制将其同步到组件。3. 在 Vue 组件中接入状态机3.1Counter.vueuseMachine 的两种关键返回值examples/7guis-1-counter-vue/src/Counter.vue 完整代码如下script setup langts import { useMachine } from xstate/vue; import { counterMachine } from ./counterMachine; const { snapshot, send } useMachine(counterMachine); /script template main classcase center-children span{{ snapshot.context.count }}/span button clicksend({ type: increase })/button /main /templateuseMachine来自xstate/vue。从源码看packages/xstate-vue/src/useMachine.ts它本质上是useActor的别名返回三个值snapshot: RefSnapshotFromTMachine—— 一个 Vue 响应式引用存放机器当前快照模板中通过snapshot.context.count读取计数send: (event) void—— 发送事件的函数模板中按钮点击时send({ type: increase })actorRef: ActorTMachine—— 底层 actor 引用需要直接操作 actor如订阅、停止时才用到。在useActor内部packages/xstate-vue/src/useActor.tsuseActorRef负责创建并持有 actoruseSelector(actorRef, (s) s)用于订阅快照变化并把最新快照写入snapshot这个 Ref —— 当assign产生新快照时Vue 的响应式系统自动触发视图更新span中的数字随之刷新。此外useActor在开发模式下会校验传入的是逻辑而非已创建的 ActorRef传错会直接抛错提示packages/xstate-vue/src/useActor.ts。3.2App.vue与main.tsApp.vueexamples/7guis-1-counter-vue/src/App.vue只是简单地渲染Counter /保持组件层级清晰main.tsexamples/7guis-1-counter-vue/src/main.ts是标准 Vue 入口createApp(App).mount(#app)。3.3 样式与 7GUIs 观感examples/7guis-1-counter-vue/src/style.css 实现了 7GUIs 演示常见的卡片 大按钮视觉.case是圆角卡片容器span以大号等宽字体显示数字button使用浅绿主题并带按下位移效果hover/focus 也做了处理。这些细节并非功能必需但让示例在演示时更接近 7GUIs 基准的呈现风格。4. 运行、构建与在线预览4.1 本地运行仓库使用 pnpm 工作区管理示例自身携带package.json与pnpm-lock.yamlexamples/7guis-1-counter-vue/package.json。在示例目录内# 安装依赖在仓库根目录或示例目录执行均可工作区会解析 xstate/vue 与 xstate pnpm install # 启动 Vite 开发服务器 pnpm devdev脚本即vite启动后按终端提示打开本地地址即可看到计数器页面。4.2 生产构建与预览package.json中的scripts提供了完整构建链路build:vue-tsc vite build—— 先执行vue-tsc对.vue与.ts做类型检查再打包到dist/。这也是验证类型安全设计的最佳实践类型不匹配会在构建期暴露preview:vite preview—— 本地预览构建产物。4.3 一键在线体验原文档提供了两个在线预览入口对应 examples/7guis-1-counter-vue/README.md 的 Live 小节CodeSandbox 与 StackBlitz 均支持直接打开本示例仓库目录运行无需本地安装适合快速体验或分享演示。5. 从源码看 XState v5 的完整链路结合上面的讲解把本例涉及的调用链串起来看定义机器setup({ types: {...} }).createMachine({...})packages/core/src/setup.ts内部把配置连同schemas交给createMachine生成StateMachine实例创建 actoruseActorRef将机器作为 actor logic 启动得到一个可接收事件的 actor发送事件send({ type: increase })把事件送入机器执行转移机器在ready状态命中on.increase执行assignresolveAssign计算新 context 并cloneMachineSnapshot出新快照packages/core/src/actions/assign.ts通知订阅者actor 发布新快照useActor中注册的 listener 更新snapshotRefpackages/xstate-vue/src/useActor.ts视图刷新Vue 响应式系统驱动模板重新渲染页面上数字 1。这条链路展示了 XState 的一个核心心智模型UI 只负责把事件交给 actor、把快照渲染出来状态如何变化、数据如何更新完全由状态机决定。这也是从 7GUIs Counter 走向更复杂状态图并行状态、守卫、子状态机、actor 通信等时的统一基础。6. 延伸把 Counter 泛化为你的第一个 XState 应用本例虽小但麻雀虽小五脏俱全。基于同一套代码骨架你可以轻松扩展增加事件在types.events中加入{ type: decrease }、{ type: reset }再在ready.on中补对应转移增加状态在states中加入counting、paused等状态用事件驱动状态切换增加守卫与延迟通过setup({ guards, delays })声明并在转移中使用guard与after复用机器setup()返回对象上的extend可以基于已有类型声明扩展 actions/guards/delayspackages/core/src/setup.ts。仓库examples/目录还提供了大量同类参考Vue 版的温度转换器examples/7guis-2-temperature-vue、React 版 Counterexamples/7guis-counter-react、带本地存储的 React 计数器examples/local-store-counter-react、计时器examples/timer与秒表examples/stopwatch等均采用同样的机器文件 框架 hook组织方式是继续学习的极佳素材。7. 小结本文围绕examples/7guis-1-counter-vue完整拆解了用 XState v5 状态机驱动 Vue 计数器的实践setup()提供类型安全入口assign不可变地更新 contextuseMachine/useActor把快照与事件桥接到 Vue 响应式系统。掌握这条链路你就掌握了 XState v5 应用的最小完备单元 —— 无论是 7GUIs 的后续任务还是真实业务中的复杂交互逻辑都可以在此基础上逐步叠加状态、守卫、子状态机与 actor 协作来构建。赞分享前端后端【免费下载链接】xstateState machines, statecharts, and actors for complex logic项目地址https://gitcode.com/gh_mirrors/xs/xstate点击查看免费下载相关推荐XState v5 实现 7GUIs CounterReact TypeScript Vite 状态机计数示例完整指南XState v5 实现 7GUIs CounterReact TypeScript Vite 状态机计数示例完整指南 本指南围绕 XState 官方前端后端XState v5 React 实战用类型安全状态机构建 7GUIs Flight Booker 航班预订表单XState v5 React 实战用类型安全状态机构建 7GUIs Flight Booker 航班预订表单 导读 本文以仓库中的 7GUIs Flig前端后端用 XState v5 状态机实现 7GUIs 温度转换器React 双向输入的事件驱动实战用 XState v5 状态机实现 7GUIs 温度转换器React 双向输入的事件驱动实战 本文以仓库内 examples/7guis temperatur前端后端上一篇Axis2 WebShell 实战基于 config.aar 的 Axis2 服务后门命令执行 / 反弹 Shell / 文件上传下载下一篇Apereo CAS 委托认证Delegated Authentication完全指南基于 Pac4j 的多协议外部身份源接入与治理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表