尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TodoMVC 应用规范(App Specification)完全解读:从目录结构到路由与持久化的实现指南

TodoMVC 应用规范(App Specification)完全解读:从目录结构到路由与持久化的实现指南 TodoMVC 应用规范App Specification完全解读从目录结构到路由与持久化的实现指南【免费下载链接】todomvcHelping you select a JavaScript framework - Todo apps for React.js, Angular, Vue and many more项目地址: https://gitcode.com/gh_mirrors/to/todomvc本文以仓库根目录的 app-spec.md 为骨架逐条拆解 TodoMVC 对每个示例应用提出的工程结构与功能交互要求并结合仓库中examples/javascript-es5、examples/backbone两个参考实现的真实源码以及 Cypress 行为测试套件说明每一项规范为什么存在、如何落地、怎样被验证。读完本文你将能够按官方标准从零实现一个外观与行为完全一致、可被自动化测试通过的 TodoMVC 应用。规范存在的意义先理解再实现app-spec.md开篇就强调We have created this short spec to help you create awesome and consistent todo apps. Make sure to not only read it but to understand it as well.——这份规范不是为了约束而约束而是要让所有框架的示例应用达到两个目标Awesome质量每个示例都遵循成熟的工程实践依赖管理、目录划分、代码风格Consistent一致无论底层是 React、Angular、Backbone 还是原生 JavaScript用户看到的界面结构、交互方式、甚至 URL 路由都完全一致从而让对比框架这件事变得公平。为此规范要求实现者以 TodoMVC 官方模板应用为基准bower.json、根目录readme.md、gulpfile.js等文件展示了这个仓库本身的组织方式并且在动手之前先实际体验其他已有应用尤其是官方推荐作为参考实现的 Backbone 应用。仓库中examples/目录下 40 余个示例正是这份规范长期演化的产物。项目结构规范推荐的目录结构规范给出了一份尽量贴近的推荐结构index.html package.json node_modules/ css └── app.css js/ ├── app.js ├── controllers/ └── models/ readme.md核心思想是按职责拆分文件、按语义放入文件夹同时允许框架自身的最佳实践优先于该结构。例如规范给出的组件拆分示例js/ ├── app.js ├── controllers/ │ └── todos.js └── models/ └── todo.js仓库中的 javascript-es5 示例 就是这一思想的直观体现src/下按职责分为store.js数据存取、model.js数据模型与业务规则、view.jsDOM 渲染与事件绑定、template.jsHTML 模板、controller.js模型与视图之间的调度、app.js组装入口六个文件各自职责单一、可独立阅读。README 要求所有示例必须附带 README说明三件事框架是什么、通用实现思路、构建过程如有。仓库中几乎每个examples/*/readme.md都遵循这一格式例如 javascript-es5 的 README 与 react 的 README。依赖管理npm 与 package.json除非与框架最佳实践冲突否则必须使用npm管理依赖且在应用根目录提供package.json。硬性要求该文件必须声明todomvc-common与todomvc-app-css两个依赖。规范给出的示例{ private: true, dependencies: { backbone: ^1.1.2, todomvc-app-css: ^1.0.0, todomvc-common: ^1.0.1 } }仓库中的 javascript-es5/package.json 完全照此执行并且额外声明了 Node/npm 版本门槛与开发脚本{ name: todomvc-javascript-es5, version: 1.0.0, private: true, engines: { node: 18.13.0, npm: 8.19.3 }, scripts: { dev: http-server ./ -p 7001 -c-1 --cors, build: node scripts/build.js, serve: http-server ./dist -p 7002 -c-1 --cors }, dependencies: { todomvc-app-css: ^2.4.2, todomvc-common: ^1.0.5 } }规范还强调.gitignore中应忽略node_modules里未被应用实际使用的文件文档、README、测试等不应进入提交只保留运行所需的最小依赖集。代码规范规范对代码风格提出了明确约束并结合 contributing.md 中的代码风格章节与仓库根目录的 codestyle.md 执行HTML 使用双引号JS 与 CSS 使用单引号。可对照 javascript-es5/index.html 与src/下的 JS 文件验证第三方依赖一律通过 npm 引入并手动清理运行不需要的文件不要直接写魔法数字用常量代替 keyCodevar ENTER_KEY 13;。这在 javascript-es5/src/view.jsthis.ENTER_KEY 13; this.ESCAPE_KEY 27;和 backbone/src/app.jsvar ENTER_KEY 13; var ESC_KEY 27;中都有体现禁止使用预处理器Sass/CoffeeScript 等以触达最广泛的读者群应用应与模板及其他示例外观和行为完全一致必须兼容仓库 contributing.md 声明的浏览器范围最新版 Chrome、Firefox、Opera、Safari 以及 IE11/Edge。此外HTML 应尽量贴近模板交付前移除模板注释base.css从 assets 引入且不得改动需要调整样式时写入app.css并保持最小改动使用模板时要同步更新相对路径。功能规范详解九大行为点这部分是规范的核心定义了应用必须呈现的全部交互行为。以下逐条解析并结合参考实现源码说明落地方式。1. 空列表状态隐藏 #main 与 #footer当没有任何 todo 时#main与#footer应被隐藏。在 javascript-es5/src/controller.js 的_updateCount中通过contentBlockVisibility命令同步控制两个区块的显示self.view.render(contentBlockVisibility, { visible: todos.total 0 });对应的 view.js 实现为contentBlockVisibility: function () { self.$main.style.display self.$footer.style.display parameter.visible ? block : none; },Backbone 参考实现的 app-view.js 则是在render()中根据app.todos.length决定$main.show()/$main.hide()与$footer.show()/$footer.hide()。Cypress 测试套件中对应用例为should hide #main and #footer与should show #main and #footer when items added见 cypress/e2e/spec.cy.js。2. 新增 Todo新 todo 在页面顶部输入框中录入规范要求页面加载时输入框应自动聚焦优先使用autofocus属性。两个参考实现的index.html都写有input classnew-todo placeholderWhat needs to be done? autofocus /见 javascript-es5/index.html 与 backbone/index.html按 Enter 创建todo追加到列表末尾并清空输入框。Backbone 的 app-view.js 中createOnEnter先判断e.which ENTER_KEY再创建必须.trim()输入值并检查非空后才允许创建。javascript-es5 的 controller.js 中Controller.prototype.addItem function (title) { if (title.trim() ) return; self.model.create(title, function () { self.view.render(clearNewTodo); self._filter(true); }); };而 model.js 在create()中再次title.trim()并默认completed: false形成入口校验 模型层兜底的双保险。对应测试用例包括should allow me to add todo items、should trim text input、should clear text input field when an item is added。3. Mark all as complete全选/取消全选该复选框将所有todo 切换到与自身相同的状态规范额外强调三点联动点击 Clear completed 后复选框的选中状态应被清除单个条目被勾选/取消时全选框应同步更新当所有 todo 都被勾选时全选框也应被勾选。javascript-es5 在_updateCount中通过一行计算实现联动controller.jsself.view.render(toggleAll, { checked: todos.completed todos.total });toggleAll的实际切换逻辑见 controller.js读取所有completed与目标状态相反的条目逐条toggleCompletesilent参数避免重复过滤。Backbone 的 app-view.js 则在渲染时维护this.allCheckbox.checked !remaining;并监听集合事件自动刷新。测试用例should allow me to mark all items as completed、should allow me to clear the complete state of all items、complete all checkbox should update state when items are completed / cleared覆盖了这条规范。4. Todo 条目的三种交互规范要求每个条目li支持三种交互点击复选框更新completed值并在父级li上切换completed类。见 view.jsView.prototype._elementComplete function (id, completed) { var listItem qs([data-id${id}]); if (!listItem) return; listItem.className completed ? completed : ; qs(input, listItem).checked completed; // 防止由非点击事件触发的状态不同步 };双击label进入编辑模式在li上切换.editing类。事件委托绑定见 view.js$delegate(self.$todoList, li label, dblclick, ...)进入编辑见_editItem第 60-74 行鼠标悬停显示删除按钮.destroy。对应事件$delegate(self.$todoList, .destroy, click, ...)。5. 编辑模式规范对编辑交互的要求最细逐条对照源码隐藏其他控件条目进入.editing状态后CSS 会隐藏.view中的控件并显示编辑输入框规范不要求 JS 干预依赖app.css中.editing的样式规则输入框聚焦并包含当前标题view.js 中动态创建input classedit后调用input.focus()并回填titleBackbone 的 todo-view.js 也执行this.$input.focus()blur 与 Enter 均保存javascript-es5 的_bindItemEditDoneview.js用 blur 事件保存并在keypress中检测ENTER_KEY后主动this.blur()从而让回车天然复用 blur 的保存路径保存时 trim空值则删除条目controller.js 的editItemSavetitle title.trim(); if (title.length ! 0) { self.model.update(id, { title: title }, ...); } else { self.removeItem(id); }Backbone 的 todo-view.jsclose()中同样实现trimmedValue ? save : clearEscape 取消编辑并丢弃修改javascript-es5 的_bindItemEditCancelview.js监听keyup检测ESCAPE_KEY先置dataset.iscanceled true再触发 blur防止取消动作误触发 blur 保存随后调用editItemCancel用模型原值重新渲染Backbone 的revertOnEscapetodo-view.js则是移除editing类并把输入框重置为model.get(title)。对应测试should allow me to edit an item、should hide other controls when editing、should save edits on blur、should trim entered text、should remove the item if an empty text string was entered、should cancel edits on escape。6. 剩余计数与复数化计数器显示未完成activetodo 的数量规范要求数字必须被strong标签包裹正确复数化0 items、1 item、2 items。javascript-es5 的 template.js 正是这一规范的直接实现Template.prototype.itemCounter function (activeTodos) { var plural activeTodos 1 ? : s; return strong${activeTodos}/strong item${plural} left; };渲染后的效果即规范示例2items left。Backbone 在 index.html 的统计模板中用 Underscore 模板等价实现strong% remaining %/strong % remaining 1 ? item : items % left。测试用例should display the current number of todo items与should display the correct text会校验这一输出。7. Clear completed 按钮点击后移除所有已完成的 todo。javascript-es5 的removeCompletedItemscontroller.js先按{ completed: true }读取模型再逐个removeItem没有已完成条目时按钮应隐藏。_updateCount中self.view.render(clearCompletedButton, { completed: todos.completed, visible: todos.completed 0, });对应的 view.js 用display: block/none控制可见性。Backbone 则通过统计模板的条件渲染实现见 index.html。测试用例为should remove completed items when clicked与should be hidden when there are no items that are completed。8. 持久化Persistence规范的核心数据要求应用应动态地将 todo 持久化到 localStorage优先使用框架自带的持久化能力如 Backbone.sync否则使用原生 localStorage条目尽量使用id、title、completed三个键localStorage 的键名格式为todos-[framework]编辑状态不得被持久化。Cypress 测试套件对持久化有专门的断言spec.cy.js 中的checkTodosInLocalStorage、checkNumberOfTodosInLocalStorage、checkCompletedKeywordInLocalStorage等辅助函数以及should persist its data用例会扫描 localStorage 中的键值检查文本、条目数量与complete关键词因此completed字段名对测试通过至关重要。仓库中两个参考实现的存储策略值得注意可以作为两种合规路径的对照Backbone 参考实现规范明确建议利用Backbone.sync。仓库的 backbone/src/sync/backbone.sync.js 重写了Backbone.sync对create/update/read/delete四种方法分别处理内存缓存中的模型并返回$.Deferred()的 promise 以兼容标准链式调用——这正是框架能力优先的示范javascript-es5 参考实现其 store.js 采用内存存储MemoryStorage以JSON.stringify模拟数据库。从源码结构看该示例以内存存储换取基准测试环境的确定性Backbone 的 app.js 中也有 Speedometer specific 的注释说明这些示例需适配基准测试运行时属于仓库内的特例规范本身要求生产形态的应用使用 localStorage 并遵循todos-[framework]命名。9. 路由Routing路由是所有实现必需的规范要求优先使用框架内置路由否则使用/assets目录中的 Flatiron Director 路由库必须实现三条路由#/all默认、#/active、#/completed#!/前缀也被允许路由变化时在模型层过滤todo 列表并在过滤链接上切换selected类过滤状态下条目被更新时视图应同步——例如在Active过滤下勾选某条目它应立即隐藏刷新后保留当前过滤状态。两个参考实现展示了框架内置路由与原生 hash 解析两种合规路径Backbone使用内置 Router。 router.js 定义routes: { *filter: setFilter }setFilter记录app.TodoFilter并触发集合的filter事件todo-view.js 的isHidden()依据TodoFilter与条目completed状态决定显隐实现模型层过滤 过滤态下更新即隐藏。URL 本身承载了刷新后过滤状态保留hash 会随刷新保留Backbone.history.start()在加载时读取javascript-es5在 app.js 中监听load与hashchange事件调用controller.setView(document.location.hash)controller.js 用locationHash.split(/)[1]解析出 | active | completed_updateFilterState维护_activeRoute并调用showAll/showActive/showCompleted三个按模型过滤的渲染方法view.js 的_setFilter则负责切换selected类View.prototype._setFilter function (currentPage) { qs(.filters .selected).className ; qs(.filters [href#/${currentPage}]).className selected; };两个示例的index.html中过滤器链接均为a href#/All/a、a href#/activeActive/a、a href#/completedCompleted/a见 backbone/index.html。测试用例包括should allow me to display active items、should allow me to display completed items、should allow me to display all items、should highlight the currently applied filter、should respect the back button。用官方浏览器测试验证一致性规范的最终裁决者是仓库的自动化测试套件。根据 tests/README.md整个测试体系的设计思路是一份参数化的 Cypress 测试脚本对每个示例应用运行同一套行为断言添加/编辑/切换/路由/持久化从而保证所有应用功能上完全相同。测试运行方式以仓库根目录为准# 运行默认精选框架集angular、preact、react、react-redux、svelte、vue npm run test:all # 运行单个框架 npm run server npx cypress run --env frameworkreact # 运行指定列表 npm run server node tests/cya.js -f vue -f svelte -f preact # 运行 examples/ 下全部未被排除的应用含 legacy 展示 npm run server node tests/cya.js --all其中tests/server.js 在http://localhost:8000提供仓库根目录静态服务cypress.config.js 将baseUrl指向http://localhost:8000/examples/测试脚本 cypress/e2e/spec.cy.js 通过Cypress.env(framework)参数化内置frameworkFolders映射构建产物在dist/的应用需先构建tests/knownIssues.js 记录各框架已知问题的跳过名单tests/excluded.js 列出多应用运行器始终跳过的框架如需要托管后端的应用。前文九个功能点的每条规范都能在这份测试脚本中找到一一对应的it(...)用例这为实现是否符合规范提供了可重复的机器验证手段。提交与长期维护义务对于想要向 TodoMVC 提交新应用的开发者contributing.md 与规范文档构成完整闭环先通读规范app-spec.md再参考最新的 Backbone 参考实现用自动化浏览器测试验证符合规范并在 PR 中附带测试输出提交前检查 issue 列表确认该框架尚未被提交或拒绝接受提交意味着长期维护义务应用需要持续跟进框架更新、修复问题若长期损坏可能被临时从站点移除。小结app-spec.md表面上是一份功能清单实质上是一套可验证的一致性契约工程结构保证示例可维护九大功能点保证体验统一路由与持久化保证状态可恢复而 Cypress 测试套件把这一切固化为可自动执行的断言。无论你计划为哪个框架编写 TodoMVC 示例都可以将本文档app-spec.md与仓库内的 javascript-es5、backbone 参考实现、codestyle.md 以及 tests/README.md 作为实现与验收的三件套依据。【免费下载链接】todomvcHelping you select a JavaScript framework - Todo apps for React.js, Angular, Vue and many more项目地址: https://gitcode.com/gh_mirrors/to/todomvc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表