news 2026/9/20 13:50:39

在 Meteor 3 + Svelte 中创建集合:从 Mongo 集合、服务端初始化到发布订阅渲染

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Meteor 3 + Svelte 中创建集合:从 Mongo 集合、服务端初始化到发布订阅渲染
  • 后端
  • 前端
  • 开发工具
  • 移动开发

【免费下载链接】meteor

Meteor, the JavaScript App Platform

项目地址:https://gitcode.com/gh_mirrors/me/meteor
点击查看免费下载

本文是 Meteor 3 + Svelte 实战教程的第二步,围绕"将静态任务列表升级为真实数据库驱动的 Todo 应用"这一核心目标,逐步讲解如何创建tasksMongo 集合、在服务端启动时初始化种子数据,并通过"发布(Publish)/订阅(Subscribe)"机制把数据同步到 Svelte 客户端进行响应式渲染。读完本章,你将掌握Mongo.Collection的创建与导入规范、Meteor 3 的*Async异步 API 用法、Meteor.startup初始化数据库的技巧,以及用Tracker.autorun在 Svelte 组件中订阅集合并触发重渲染的完整链路。

为什么需要集合(Collections)

Meteor 已经为你内置好了 MongoDB——你不需要手动安装、启动或配置数据库服务。但要真正把数据存下来,我们需要先创建"集合(Collection)",它是存放"文档(Document)"的地方。在本项目中,我们要存放的文档就是我们的tasks(任务)。

集合是 Meteor 数据层的核心抽象。当你在创建集合时传入一个name字符串,你就声明了一个持久化集合:它存储在服务端的 MongoDB 中,对所有用户可见,客户端和服务端可以用完全相同的 API 访问它。根据 v3-docs/docs/api/collections.md 的说明:

  • 服务端(不指定connection时),同名集合会创建在底层的 Mongo 服务器上,你对集合调用的方法会(在通过访问控制规则检查后)直接翻译为普通的 Mongo 操作;
  • 客户端,会创建一个 Minimongo 实例——它是用纯 JavaScript 实现的内存版 Mongo,作为本地缓存存放当前客户端正在使用的那部分数据,find()查询直接命中缓存,无需与服务器通信;
  • 当你在客户端写入数据库时(insert/update/remove),命令会先在本地立即执行,同时通过 stubs 机制发送到服务端执行。

这一"本地即时生效 + 服务端同步"的设计,正是 Meteor 免写 REST 接口的底气所在,也是本章后续发布订阅机制的基础。

2.1:创建 Tasks 集合

创建一个新文件imports/api/TasksCollection.js,它实例化一个新的 Mongo 集合并导出它:

import { Mongo } from "meteor/mongo"; export const TasksCollection = new Mongo.Collection("tasks");

这里做了两件关键的事情:

  1. meteor/mongo包导入Mongo命名空间,其中包含Mongo.Collection构造器;
  2. 用名称"tasks"创建一个持久化集合并导出。

注意我们将文件放在了imports/api目录下——这是存放 API 相关代码(如 publications 发布、methods 方法)的约定位置。目录名完全取决于个人偏好,但遵循这一惯例能让项目结构更清晰、更易维护。

如果启动项目自带了imports/api/links.js文件,现在可以删掉它,因为本教程用不到。

关于应用结构以及 import/export 的更多说明,可参考项目中的模块文档(如 v3-docs/docs/api/collections.md 与 v3-docs/docs/packages/modules.md)。

从源码看Mongo.Collection的底层行为

在 packages/mongo/mongo_common.js 与 packages/mongo/collection/methods_async.js 中可以印证这一行为:传入name时,服务端将集合落到后端 Mongo 驱动上,客户端则建立 Minimongo 缓存实例;不传name(传null)时创建的是本地集合——不同步到任何地方,只是一个支持 Mongo 风格find/insert/update/remove的本地草稿本,客户端与服务端都用 Minimongo 实现。

Meteor 3 之后,同步写方法在服务端会直接抛错。因此本教程中统一使用*Async异步版本,例如insertAsyncfind().countAsync(),这是 Meteor 3.x 及以后的强制约定(详见 v3-docs/docs/api/collections.md 中的 danger 提示)。

2.2:初始化 Tasks 集合(服务端种子数据)

集合要真正工作,需要在服务端导入它,以便 Meteor 为其建立所需的底层管道。你可以用以下两种方式之一导入:

import "/imports/api/TasksCollection"; // 仅导入副作用 import { TasksCollection } from "/imports/api/TasksCollection"; // 导入并在本文件使用

如果要在同一个文件中使用它,就采用第二种写法;无论如何,确保它被导入了

导入之后,判断集合中是否有数据变得非常简单;如果没有,我们就可以很方便地插入一些示例数据。server/main.js中原来的内容不再需要,替换为:

import { Meteor } from "meteor/meteor"; import { TasksCollection } from "/imports/api/TasksCollection"; const insertTask = async (taskText) => await TasksCollection.insertAsync({ text: taskText }); Meteor.startup(async () => { if (await TasksCollection.find().countAsync() === 0) { [ "First Task", "Second Task", "Third Task", "Fourth Task", "Fifth Task", "Sixth Task", "Seventh Task", ].forEach(insertTask); } });

这段代码做的事情是:导入TasksCollection,然后遍历一个字符串数组,对每个字符串调用一个插入函数,把该字符串作为task文档的text字段写入集合。

值得注意的几个细节:

  • Meteor.startup:保证这段代码在 Meteor 服务端就绪后才运行。根据 v3-docs/docs/api/meteor.md,Meteor.startup中的代码总是在所有应用代码加载完成后执行,是初始化数据库的推荐位置。
  • 幂等初始化countAsync() === 0检查确保只在集合为空时插入种子数据,避免应用重启(每次代码保存都会触发自动重启)后重复插入七条重复任务。这是开发阶段最常用的"空库填充"模式。
  • insertAsync的异步契约:在 packages/mongo/collection/methods_async.js 中可以看到,insertAsync(doc)最终调用_insertAsync(doc, options):它会浅拷贝文档、在缺少_id时用_makeNewID()生成 ID、校验_id必须是非空字符串或Mongo.ObjectID,然后返回一个 Promise,resolve 出文档的唯一_id。服务端本地集合则直接下沉到 Mongo 驱动执行(this._collection.insertAsync(doc))。

2.3:用 Svelte 渲染 Tasks 集合

接下来进入最有趣的部分:用 Svelte 渲染集合数据。这非常简单。

App.svelte文件中,导入TasksCollection,不再返回静态数组,而是返回数据库里保存的任务:

<script> import { Meteor } from "meteor/meteor"; import { Tracker } from "meteor/tracker"; import { onMount, onDestroy } from "svelte"; import { TasksCollection } from "../api/TasksCollection"; // 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().fetch(); }); return () => { computation?.stop?.(); handle?.stop?.(); }; }); onDestroy(() => { computation?.stop?.(); handle?.stop?.(); }); </script> <div class="container"> <header> <h1>Todo List</h1> </header> <ul> {#if subIsReady} {#each tasks as task (task._id)} <li>{task.text}</li> {/each} {:else} <div>Loading ...</div> {/if} </ul> </div>

这段组件代码中包含了 Meteor + Svelte 集成最关键的四块拼图:

  1. Meteor.subscribe("tasks"):在组件挂载(onMount)时向服务端发起订阅,返回值handle用于跟踪订阅状态(handle.ready())并在组件卸载时停止订阅;
  2. Tracker.autorun:注册一个响应式计算。每次handle.ready()状态变化或TasksCollection.find().fetch()的查询结果变化时,它都会重新执行,把最新数据写入tasks变量,从而触发 Svelte 的 UI 更新。这正是 Svelte 的声明式响应式与 Meteor 的 Tracker 响应式系统对接的桥梁;
  3. onDestroy/ onMount 返回值中的清理函数:通过computation?.stop?.()handle?.stop?.()停止响应式计算与订阅,防止内存泄漏与重复订阅;
  4. {#if subIsReady}{:else}:订阅未就绪时显示 "Loading ...",就绪后使用{#each tasks as task (task._id)}遍历渲染,key 使用task._id以保证列表 diff 的高效与稳定。

等一下!有个东西缺失了。如果现在运行应用,你会发现任务一个都没有渲染出来。

这是因为我们还需要把数据发布给客户端

发布与订阅:把 MongoDB 同步到客户端

Meteor 不需要 REST 调用。它依赖的是把服务端的 MongoDB 与客户端的 MiniMongoDB 同步:首先在服务端发布集合,然后在客户端订阅它们,数据便沿着 DDP 协议自动流向客户端。

关于 Publications/Subscriptions 的更多信息,可参考 v3-docs/docs/api/meteor.md 中的 Publish and subscribe 章节。

第一步:创建发布(Publication)

为我们的任务创建一个发布:

import { Meteor } from "meteor/meteor"; import { TasksCollection } from "./TasksCollection"; Meteor.publish("tasks", function () { return TasksCollection.find(); });

发布函数返回一个Collection.Cursor,Meteor 会把该游标命中的文档发布给每个订阅它的客户端。你也可以返回一个游标数组(但多个游标目前必须来自不同集合),或者使用底层的added/changed/removed低层接口手动控制发布集合——当不返回游标时必须调用ready()通知客户端初始记录集已完成。

从 packages/ddp-server/livedata_server.js 的源码可以看到,服务端为每个订阅调用publish_handlers中注册的发布函数,并将结果交给_publishCursor开始观察游标、把数据通过 DDP 推送给客户端;发布还支持多种publicationStrategies(如SERVER_MERGE默认策略)来决定多条发布数据的合并方式。这里返回TasksCollection.find()意味着把整个 tasks 集合发布给所有订阅者——对于 Todo 教程完全够用,但在真实项目中你通常会按this.userId或参数过滤,只发布当前用户的数据。

第二步:在服务端导入发布文件

现在,把这个发布文件导入到服务端:

... import { TasksCollection } from '/imports/api/TasksCollection'; import "../imports/api/TasksPublications"; // [!code highlight] const insertTask = taskText => TasksCollection.insertAsync({ text: taskText }); ...

第三步:订阅发布(已在组件中完成)

剩下的唯一一步就是订阅这个发布——我们在上面的App.svelte中已经用 Tracker 和生命周期钩子完成了:

... onMount(() => { handle = Meteor.subscribe("tasks"); computation = Tracker.autorun(() => { // Reactive code here }); }); ...

完整数据流回顾

至此,整个链路已经闭合:

  1. 服务端启动时(Meteor.startup),tasks集合被播种了 7 条示例数据;
  2. TasksPublications.js注册了名为"tasks"的发布,把整个集合的游标暴露给客户端;
  3. Svelte 组件挂载时调用Meteor.subscribe("tasks"),数据通过 DDP 协议从服务端 MongoDB 同步到客户端的 Minimongo 缓存;
  4. Tracker.autorun感知到订阅就绪与查询结果变化,把TasksCollection.find().fetch()的结果写入 Svelte 响应式变量tasks
  5. Svelte 响应式渲染<li>列表。

现在你的应用应该长这样了:

这一切是响应式的:你可以直接在服务端的 MongoDB 中修改数据,你的应用会立即做出反应并重新渲染,无需刷新页面、无需手写任何同步代码。

连接 MongoDB:查看与操作你的数据

你可以在应用目录下的终端中运行meteor mongo直接连接 MongoDB,也可以使用 Mongo 图形化客户端(如 NoSQLBooster)进行连接。Meteor 内置的 MongoDB 运行在3001端口。

首先,在 NoSQLBooster 等客户端中新建连接,服务器地址填localhost,端口填3001

连接成功后,你会看到名为meteor的数据库,其下包含links(若未删除)、tasksusers等集合:

双击tasks集合即可查看其中存储的文档,每个文档都包含_idtext两个字段:

关于连接参数的补充说明:MONGO_URL环境变量用于指定 MongoDB 服务端地址(格式如mongodb://user:password@myserver.com:10139),MONGO_OPLOG_URL则用于配置 oplog 观察驱动以提升实时同步效率(详见 v3-docs/docs/cli/environment-variables.md)。本教程场景下使用 Meteor 内置的嵌入式 MongoDB,默认监听3001端口,无需额外配置即可连接。

小结与下一步

本章完成了从"静态假数据"到"数据库驱动"的关键跨越:

知识点核心内容
创建集合new Mongo.Collection("tasks")并放在imports/api导出
服务端初始化Meteor.startup+countAsync() === 0幂等播种种子数据
异步 APIMeteor 3 服务端强制使用insertAsync/countAsync*Async方法
发布Meteor.publish("tasks", () => TasksCollection.find())
订阅SvelteonMountMeteor.subscribe("tasks")+Tracker.autorun响应式取数
响应式渲染数据变化自动触发 Svelte 重渲染,客户端缓存 Minimongo 与服务端 MongoDB 实时同步
数据可视化meteor mongo或 NoSQLBooster 连接localhost:3001查看数据库

在下一步中,我们将使用表单来创建任务,把"添加任务"的能力真正交到用户手里。

  • 后端
  • 前端
  • 开发工具
  • 移动开发

【免费下载链接】meteor

Meteor, the JavaScript App Platform

项目地址:https://gitcode.com/gh_mirrors/me/meteor
点击查看免费下载
上一篇:从论文到代码:DeepCpG-DNA模型训练细节与参数调优秘籍
下一篇:从零部署到高效微调:Qwen3-4B-Instruct-2507开源大模型实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 13:47:57

Email Verification API 规范 Accounts Validation 算法逐行讲解

Email Verification API 规范 Accounts Validation 算法逐行讲解 【免费下载链接】email-verification verified autofill 项目地址: https://gitcode.com/GitHub_Trending/em/email-verification Email Verification API&#xff08;邮件验证协议 EVP&#xff09;是 W…

作者头像 李华
网站建设 2026/9/20 13:45:23

Halcon + C#:工业读码与OCR识别的落地方案

简介&#xff1a;这份资源是一套基于 C# 与 Halcon 的二维码深度识别与 OCR 示例工程&#xff0c;面向需要在 Windows 桌面应用中集成机器视觉能力的开发者和自动化项目人员。项目以 WindowsFormsApp1 为入口&#xff0c;完整演示了图像捕获、预处理、二维码定位与解码、文字识…

作者头像 李华
网站建设 2026/9/20 13:40:56

编码智能体执行框架(Harness)设计实证研究

编码智能体执行框架&#xff08;Harness&#xff09;设计实证研究 arXiv编号&#xff1a;arXiv:2609.20804v1 [cs.AI] 摘要 编码智能体执行框架&#xff08;coding harness&#xff09;决定大模型如何把模型原生能力转化为长视界软件工程任务性能。现有工作大多将执行框架作为完…

作者头像 李华