资讯详情

Meteor 3 + Svelte 教程第 6 步:任务筛选、待办计数与响应式状态管理

📅 2026/9/20 16:07:58 | 华诺云谱 👁 阅读
Meteor 3 + Svelte 教程第 6 步:任务筛选、待办计数与响应式状态管理
后端前端开发工具移动开发【免费下载链接】meteorMeteor, the JavaScript App Platform项目地址https://gitcode.com/gh_mirrors/me/meteor点击查看免费下载本步骤为 Meteor 官方 Svelte 教程的第六课聚焦于为 Todo 应用实现按状态筛选任务与待办数量统计两大功能。你将学习如何在 Svelte 组件中用响应式变量维护hideCompleted状态、通过 Meteor MiniMongo 的$ne查询对任务列表做条件筛选并结合Tracker.autorun在订阅数据变化时自动重算待办数量。学完本节你将掌握 Meteor Svelte 组合下响应式状态 响应式查询 条件渲染的完整实战套路并学会用 Meteor DevTools 插件调试客户端数据库与 DDP 消息。本文对应的官方教程文档为 v3-docs/docs/tutorials/svelte/6.filter-tasks.md是 Meteor 3 版 Svelte 入门教程从创建应用到部署中的第六个步骤前置内容包括创建集合与发布/订阅2.collections.md、表单与 Meteor Methods3.forms-and-events.md、勾选与删除任务4.update-and-remove.md。本步骤将复用前文建立好的TasksCollection、tasks发布与tasks.insert方法。本节目标在开始之前先明确本节要达成的三个结果新增隐藏已完成任务开关点击按钮即可在全部任务和未完成任务两种视图间切换显示待办数量在应用栏标题旁实时显示未完成任务的个数无待办时不显示(0)保持响应式无论任务被勾选、删除还是新增界面都自动随之更新无需手动刷新。其中第 2、3 点是本节的关键——筛选结果与计数都必须由响应式数据驱动而不是在某个事件里一次性计算。6.1 响应式状态hideCompleted 与 toggleHideCompleted在 Svelte 中我们直接在script标签里用普通变量管理组件状态。Svelte 的编译器会在编译期分析这些变量的赋值行为并把它们变成响应式的——当变量被重新赋值时依赖它的 DOM 会自动更新这正是 Svelte 相比手动调用框架 API 的独特之处。添加状态变量与切换函数在imports/ui/App.svelte的script中新增两个关键代码let hideCompleted false;记录当前是否隐藏已完成任务function toggleHideCompleted() { hideCompleted !hideCompleted; }负责反转该状态。script import { Meteor } from meteor/meteor; import { Tracker } from meteor/tracker; import { onMount, onDestroy } from svelte; import { TasksCollection } from ../api/TasksCollection; import /imports/api/TasksMethods; import Task from ./Task.svelte; let newTask ; let hideCompleted false; async function addTask(event) { event.preventDefault(); if (newTask.trim()) { await Meteor.callAsync(tasks.insert, { text: newTask, createdAt: new Date(), }); newTask ; } } function toggleHideCompleted() { hideCompleted !hideCompleted; } // Reactive state let handle; let subIsReady false; let tasks []; let computation; onMount(() { handle Meteor.subscribe(tasks); computation Tracker.autorun(() { subIsReady handle.ready(); tasks TasksCollection.find({}, { sort: { createdAt: -1, _id: -1 } }).fetch(); }); return () { computation?.stop?.(); handle?.stop?.(); }; }); onDestroy(() { computation?.stop?.(); handle?.stop?.(); }); /script说明6.3 节会在Tracker.autorun内部使用hideCompleted做条件查询届时请务必保留import { Tracker } from meteor/tracker;以及onMount/onDestroy的导入它们是本节响应式管线的核心依赖。在标记中添加切换按钮在div classmain内、任务列表ul之前插入一个.filter容器与切换按钮。按钮文案用 Svelte 的{#if}条件块渲染hideCompleted为true时显示Show All否则显示Hide Completeddiv classapp header div classapp-bar div classapp-header h1️ Todo List/h1 /div /div /header div classmain form classtask-form on:submit{addTask} input typetext placeholderType to add new tasks bind:value{newTask} / button typesubmitAdd Task/button /form div classfilter button on:click{toggleHideCompleted} {#if hideCompleted} Show All {:else} Hide Completed {/if} /button /div ul classtasks {#if subIsReady} {#each tasks as task (task._id)} Task {task} / {/each} {:else} divLoading .../div {/if} /ul /div /div这里的{#if}是 Svelte 的条件渲染块语法{:else}是它的分支与{#each}一样是模板层的核心控制流点击按钮后toggleHideCompleted更新hideCompleted按钮文字随即在两种文案之间切换。注意{#each tasks as task (task._id)}以task._id作为每个条目的 key保证列表 diff 的稳定性。6.2 按钮样式浏览器默认的button外观是灰底、对比度不足因此官方教程建议为筛选按钮补充样式。在client/main.css中加入如下规则外层.filter用 Flexbox 让按钮水平居中内层.filter button使用主题色#62807e一种青灰色作为背景让按钮与页面整体风格协调.filter { display: flex; justify-content: center; } .filter button { background-color: #62807e; }这段 CSS 与教程第 5 步5.styles.md引入的 Flexbox 布局体系一脉相承client/main.css是 Meteor 应用客户端全局样式的默认入口。按钮有了对比度之后用户能一眼看出它是一个可交互控件。6.3 筛选任务$ne 查询 响应式计数现在把筛选逻辑接入数据层。核心思路是在Tracker.autorun的响应式函数里根据hideCompleted动态构造查询条件——只要hideCompleted或集合数据发生变化autorun就会自动重跑重新fetch()任务列表并重算计数。响应式筛选与计数的完整实现script import { Meteor } from meteor/meteor; import { Tracker } from meteor/tracker; import { onMount, onDestroy } from svelte; import { TasksCollection } from ../api/TasksCollection; import /imports/api/TasksMethods; import Task from ./Task.svelte; let newTask ; let hideCompleted false; async function addTask(event) { event.preventDefault(); if (newTask.trim()) { await Meteor.callAsync(tasks.insert, { text: newTask, createdAt: new Date(), }); newTask ; } } function toggleHideCompleted() { hideCompleted !hideCompleted; } // Reactive state let handle; let subIsReady false; let tasks []; let incompleteCount 0; let computation; $: incompleteDisplay incompleteCount 0 ? (${incompleteCount}) : ; onMount(() { handle Meteor.subscribe(tasks); computation Tracker.autorun(() { subIsReady handle.ready(); // Reactive tasks with filter tasks TasksCollection.find( hideCompleted ? { isChecked: { $ne: true } } : {}, { sort: { createdAt: -1, _id: -1 } } ).fetch(); // Reactive incomplete count incompleteCount TasksCollection.find({ isChecked: { $ne: true } }).count(); }); return () { computation?.stop?.(); handle?.stop?.(); }; }); onDestroy(() { computation?.stop?.(); handle?.stop?.(); }); /script逐行拆解本节新增/变更的部分条件查询hideCompleted ? { isChecked: { $ne: true } } : {}。当用户点击隐藏已完成时查询条件变为{ isChecked: { $ne: true } }即isChecked不等于true的文档否则传{}查询全部。$ne是 MongoDB 的不等于操作符注意它同时匹配字段不存在或字段值为false的文档——这一点很关键因为本教程第 4 步之前插入的任务根本没有isChecked字段用$ne: true恰好能把这些从未被勾选的旧任务也归入未完成队列。计数查询TasksCollection.find({ isChecked: { $ne: true } }).count()统计当前客户端 MiniMongo 中未完成任务的条数并把结果赋给响应式变量incompleteCount。find()返回游标cursorcount()返回匹配文档数两者都不会触发全量文档传输。排序稳定性sort: { createdAt: -1, _id: -1 }在按createdAt倒序的基础上追加_id倒序作为次级排序键。正如教程第 4 步所指出的当多个任务在同一毫秒内被插入createdAt相同时仅靠时间排序会导致列表在勾选、删除等响应式更新时跳动追加_id次级排序可保证顺序确定性。Svelte 响应式语句$: incompleteDisplay incompleteCount 0 ? \(${incompleteCount}) : ;是 Svelte 的响应式声明语法reactive statement。每当incompleteCount变化incompleteDisplay自动重算待办大于 0 时生成(n)形式的展示字符串否则为空字符串——这样就避免了在标题栏出现难看的(0)。底层原理Tracker.autorun 为什么自动重跑Tracker.autorun是 Meteor 响应式体系Tracker的核心 API。从 packages/tracker/tracker.js 的源码注释可以看到Tracker.Computation代表一段会因响应式数据变化而反复重跑的执行体——Computations dont have return values; they just perform actions, such as rerendering a template on the screen。当autorun的回调函数内访问了某个响应式数据源例如 MiniMongo 的find().fetch()、订阅句柄的ready()时Tracker 会自动把这些数据源注册为该 computation 的依赖一旦任一依赖失效数据变化Meteor 调度器就把该 computation 标记为 invalidated并在合适的时机重跑。具体到本节代码handle.ready()与TasksCollection.find(...).fetch()/.count()都是响应式数据源hideCompleted虽是 Svelte 的普通变量但每当你点击按钮修改它时Svelte 会触发组件重渲染重新执行onMount里注册的Tracker.autorun回调——更准确地说Meteor 的minimongo订阅会感知数据源变化autorun重跑时读到最新的hideCompleted值从而换用新的查询条件。于是点击按钮 → 切换查询条件 → 重新 fetch → 界面刷新形成了一条完整的响应式链路这正是 Meteor 区别于传统 REST 手动状态同步的核心体验数据变化自动驱动 UI无需手动派发更新。生命周期为什么不直接写Tracker.autorunTracker.autorun创建的 computation 需要手动停止否则组件卸载后它仍会持续监听并尝试更新已销毁的组件。因此教程把autorun放在 Svelte 的onMount组件挂载后创建中并在onMount返回的清理函数与onDestroy组件销毁前两处都调用computation?.stop?.()与handle?.stop?.()。这样无论组件以何种方式卸载订阅与计算都会正确释放避免内存泄漏与卸载后 setState之类的告警。这也是 Svelte 生命周期钩子与 Meteor 响应式体系协同的推荐写法。6.4 调试利器Meteor DevTools Evolved 扩展筛选逻辑写完后你可能想知道MiniMongo 里到底有哪些数据DDP 在客户端与服务端之间传了什么。官方教程推荐安装 Chrome 扩展Meteor DevTools Evolved来可视化调试。它能做什么查看 MiniMongo 数据扩展会列出应用中所有集合你可以直接看到每个集合在客户端缓存MiniMongo中的文档内容验证筛选条件是否命中、数据是否按预期同步监听 DDP 消息DDPDistributed Data Protocol是 Meteor 客户端与服务端通信的协议发布/订阅与方法调用的底层载体。扩展可以展示 Meteor 正在发送和接收的每一条 DDP 消息帮助你理解Meteor.subscribe与Meteor.callAsync背后发生了什么——这对学习 Meteor 的工作原理尤其有帮助。在 Chrome 网上应用店搜索并安装Meteor DevTools Evolvedibniinmoafhgbifjojidlagmggecmpgf后打开你的应用页面即可在开发者工具中看到对应的面板。下图展示了扩展查看 MiniMongo 数据与 DDP 消息的界面效果教程原文指出该扩展同时提供了 教程文档 中对应的安装链接实际安装时请以 Chrome 网上应用店当前页面为准。6.5 在应用栏显示待办数量最后一步是把第 6.3 节算出的incompleteDisplay渲染到应用栏的标题中。将h1从静态的️ Todo List改为插值形式在标题后追加待办计数div classapp header div classapp-bar div classapp-header h1️ To Do List {incompleteDisplay}/h1 /div /div /header !-- rest of markup -- /div由于incompleteDisplay是响应式声明$:它随incompleteCount实时变化新增任务、勾选完成、删除任务或切换筛选视图时标题右侧的(n)都会自动增减当incompleteCount为 0 时incompleteDisplay为空串标题恢复为干净的️ To Do List不会出现多余的(0)。完成后你的应用应该呈现出两种视图未筛选时展示全部任务并显示总待办数点击 Hide Completed 后仅展示未完成任务本节回顾与验证清单按顺序检查以下行为是否符合预期即可确认本节实现正确切换视图点击 Hide Completed已完成isChecked: true的任务从列表消失按钮文字变为 Show All再次点击恢复全部任务待办计数标题中的(n)随未完成任务数变化全部完成时括号消失响应式联动在筛选视图下勾选/取消勾选任务、新增或删除任务列表与计数即时更新无泄漏组件卸载如切换页面后没有报错订阅与 computation 均被正确清理调试可视化可选通过 Meteor DevTools Evolved 观察tasks集合的 MiniMongo 内容与 DDP 消息确认$ne查询筛选的是客户端缓存数据而完整的tasks文档仍由tasks发布2.collections.md 中的Meteor.publish(tasks, ...)按需推送到客户端。延伸阅读响应式查询的底层集合实现packages/mongo/collection/collection.jsMongo.Collection的find/count与_id生成逻辑Tracker 响应式引擎源码与计算对象说明packages/tracker/tracker.js本节前置步骤集合与发布订阅 2.collections.md、表单与方法 3.forms-and-events.md、勾选与删除 4.update-and-remove.md下一步教程将在此基础上为应用加入用户账户体系7.adding-user-accounts.md届时筛选与计数逻辑会成为仅展示当前用户任务的重要基础。赞分享后端前端开发工具移动开发【免费下载链接】meteorMeteor, the JavaScript App Platform项目地址https://gitcode.com/gh_mirrors/me/meteor点击查看免费下载相关推荐Meteor 3 React 教程用 useState 与 Mini Mongo 查询过滤任务列表并统计待办数Meteor 3 React 教程用 useState 与 Mini Mongo 查询过滤任务列表并统计待办数 本文是 Meteor 官方 React 教后端前端开发工具移动开发Meteor 3 Svelte 实战任务更新与删除的完整实现Todo 应用第 4 步Meteor 3 Svelte 实战任务更新与删除的完整实现Todo 应用第 4 步 本篇教程以 Meteor 官方教程 Svelte 版的第 4 步后端前端开发工具移动开发Svelte Flow响应式编程xyflow Reactive模式Svelte Flow响应式编程xyflow Reactive模式 响应式数据流架构解析 Svelte Flow基于Svelte的编译时响应式系统构建采用前端UI组件图表库上一篇【亲测免费】Fira Code 常见问题解决方案从安装到高级配置全攻略下一篇告别代码混乱Fira Code 字体安装与配置完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。