资讯动态

Omi架构实战:用贪吃蛇游戏理解两层架构与三层架构的选择

发布时间:2026/9/22 22:09:43 来源:尧图企业网站定制
Omi架构实战用贪吃蛇游戏理解两层架构与三层架构的选择【免费下载链接】omiWeb Components Framework - Web组件框架项目地址: https://gitcode.com/gh_mirrors/om/omiOmi是一个轻量 Web Components 框架内置 Signal 响应式信号。Omi 官方用同一款贪吃蛇游戏实现了两种架构基于Signal类的两层架构和基于响应式函数的三层架构。本文带你用 5 分钟看懂它们的差异并给出明确的选择建议——帮你快速判断自己的项目该用哪种 Omi 架构。为什么贪吃蛇是理解 Omi 架构的最佳样本贪吃蛇麻雀虽小五脏俱全它有游戏状态地图、蛇身、暂停标记、业务逻辑移动、吃食物、变长和用户交互转向、调速、重开。这三种角色恰好对应了前端架构中最核心的分层问题。Omi 仓库里并排放着两个几乎一样的贪吃蛇游戏区别只有一句话snake-game-2tier —— 基于 OmiSignalclass 的两层架构snake-game-3tier —— 基于 Omi 响应式函数的三层架构先来看看 Omi 框架整体长什么样下面这张图是 Omi 响应式信号的数据流示意两层架构Model 即状态目录结构与角色分工两层架构非常直接整个项目只有两层Model数据 逻辑和View视图。snake-game-2tier/src ├── index.tsx # 入口创建 Game 并注入全局 ├── models/ │ ├── game.ts # GameModel继承 Signal状态与逻辑都在这里 │ └── snake.ts # SnakeModel纯蛇的移动逻辑 └── views/ ├── game/index.tsx # 控制区视图按钮 └── screen/index.tsx # 游戏画面视图16x16 网格核心设计在 game.ts 里——Game直接继承 Omi 的Signal类class Game extends SignalSignalValueType { // 状态放在 this.value 里{ map, paused } bind pauseOrPlay() { this.value.paused !this.value.paused this.update() // 改完值手动通知视图刷新 } }模式很简单改this.value→ 调this.update()→ 视图自动重渲染。视图如何消费 Model入口 index.tsx 创建唯一的 Game 实例用 Omi 的mixin注入到所有组件视图组件 views/game/index.tsx 直接调用 Model 上的方法div classbtn onClick{game.snake.turnUp}Up/div div classbtn onClick{game.reset}Reset/div span{game.value.paused ? Play : Pause}/span没有中间层视图和 Model 是直连的。三层架构插入一个 Store多出来的那个目录对比两个项目的目录差异一目了然——三层架构多了一个stores/目录snake-game-3tier/src ├── models/ # 和两层版几乎相同但 Game 不再继承 Signal ├── stores/ │ └── index.ts # ⭐ 新增的 Store 层持有状态转接一切操作 └── views/ # 视图不再 import Model只 import Store在 stores/index.ts 中Store做了三件事创建 Modelnew Game({ onTick })并把每帧回调指向自己的state.update()持有状态用 Omi 的响应式函数signal()创建state暴露操作turnUp、reset等bind方法全部转发给 Model。export class Store { bind turnUp() { this.snake.turnUp() // 视图永远只调用 Store 的方法 } }Model 变成了纯业务类这是两种架构最本质的区别。三层版里的 game.ts 是一个普通 class不继承 Signal、不 import Omi、不认识视图——它通过构造函数接收onTick回调来通知外部我这一帧跑完了class Game { constructor(options) { this.onTick options.onTick // 由 Store 注入 } tick() { // ... 移动、吃食物、标记格子 this.onTick() // 我不直接更新 UI只发信号 } }于是依赖关系变成单向的View → Store → ModelModel 对上层完全无感知。两种架构差异速览维度两层架构snake-game-2tier三层架构snake-game-3tier状态载体Model 继承Signal类Store 使用signal()函数状态位置Model 内部this.valueStore 中与 Model 分离视图依赖对象直接持有 Model只持有 StoreModel 是否感知 Omi是import 自 omi否纯业务逻辑手动刷新点Model 里调用this.update()Store 里调用state.update()适合规模小工具、单组件应用多组件共享状态、需要测试的业务我该选哪种架构一份决策清单选两层架构如果项目就是一个单页面小工具计数器、小游戏、表单状态只有一个组件在读不存在跨组件共享希望代码路径最短Signal类把状态和操作收在同一个对象里写起来最省。选三层架构如果多个组件都要读同一份状态比如游戏画面和控制区希望 Model 变成可独立单测的纯逻辑——它不依赖任何框架 API未来可能换视图层Store 这一层让状态管理与渲染解耦。 一句话总结两层是 Signal 类的内聚式用法三层是响应式函数的解耦式用法。状态共享范围决定分层深度——不共享就两层共享了就三层。本地运行两步跑起来克隆 Omi 仓库git clone https://gitcode.com/gh_mirrors/om/omi进入任一模板启动开发服务器cd omi/packages/snake-game-2tier npm install npm start把路径换成snake-game-3tier即可体验三层版。两个游戏功能完全一致边玩边对照源码架构差异会非常直观。延伸阅读想继续深入 Omi 的响应式体系可以参考仓库内这些资料框架主包与示例packages/omi/含 signal.tsx、signal-object.tsx独立响应式信号库packages/reactive-signal/中文入门文档getting-started.md、reactivity.md从贪吃蛇到真实业务Omi 的两层与三层架构给出的不是二选一的难题而是一个随项目复杂度自然生长的答案。【免费下载链接】omiWeb Components Framework - Web组件框架项目地址: https://gitcode.com/gh_mirrors/om/omi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价