Meteor 3 + Solid 实战:创建与渲染 MongoDB Collections 完整指南
2026/9/20 8:02:47 网站建设 项目流程
  • 后端
  • 前端
  • 开发工具
  • 移动开发

【免费下载链接】meteor

Meteor, the JavaScript App Platform

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

本篇是 Meteor 3 + Solid 教程系列的第二篇,承接创建应用之后,手把手讲解如何在 Meteor 中创建 MongoDB 集合(Collection)、在服务端初始化种子数据、通过发布/订阅(Publish/Subscribe)把数据同步到客户端,并用 Solid 的响应式原语渲染任务列表。读完本文你将掌握 Meteor 的Mongo.Collection、异步 API(insertAsync/fetchAsync/countAsync)、Tracker.autorun与 Solid Signals 的整合,以及如何用meteor mongo或 GUI 客户端连接数据库查看文档。

前置准备:Solid 项目与目录约定

本文基于上一篇教程创建的项目继续开发。如果你还没有项目,先执行:

meteor create --solid simple-todos-solid

--solid选项会生成一个使用 Solid 作为 UI 框架、Rspack 作为打包器(Meteor 3.4+ 的默认构建栈)的项目,详见 Rspack 打包器集成。运行meteor即可启动应用。

Meteor 已经为你内置了 MongoDB(无需单独安装),但我们还需要在代码中创建自己的集合(collection)——它是我们存储文档(documents)的地方,在本教程中用来存放tasks

在动手前,先明确一个目录约定:本文所有 API 相关代码(集合、发布、方法)都放在imports/api目录下。这只是一个约定而非强制,你可以随意命名。Meteor 应用的结构规范和 ES2015import/export模块机制,可以参考应用结构教程。

如果起始项目里存在imports/api/links.js文件,现在可以删除,我们不再需要它。

创建 Tasks 集合

imports/api下新建TasksCollection.js,实例化一个 Mongo 集合并导出:

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

这里有两件关键的事:

  • meteor/mongo导入Mongo:这是 Atmosphere 包(Meteor 生态的包格式)的标准导入方式,路径必须以meteor/前缀开头,以与 npm 包命名空间区分。
  • new Mongo.Collection("tasks")"tasks"是集合名称,也是 MongoDB 中实际的集合名。这个实例同时存在于客户端与服务端:在服务端它直接驱动 MongoDB,在客户端它驱动内存中的 Minimongo(详见后文"数据同步机制"一节)。

集合的完整 API 可以参考 Collections API 文档。

初始化集合与种子数据

集合定义好之后,还需要在服务端导入它,Meteor 才会完成相应的底层管道(plumbing)设置。

你有两种导入方式:

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

注意这里使用了/开头的绝对导入路径,指向项目根目录,这是 Meteor 推荐的写法。第一种适合只需确保集合被加载的场景;如果要在同一文件里使用集合,就用第二种。

现在我们可以很方便地检查集合里是否有数据,没有的话就插入一些示例数据。用下面的内容替换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); } });

这段代码做了什么:

  1. Meteor.startup(async () => {...}):应用服务端启动时执行的回调(即 Node.js 进程启动阶段)。
  2. TasksCollection.find().countAsync():统计集合中所有文档的数量。注意这里用的是Async 后缀版本——这是 Meteor 3(基于 async/await 的现代架构)的核心变化之一。
  3. TasksCollection.insertAsync({ text: taskText }):异步插入一条文档,text字段保存任务文本。
  4. 幂等初始化:只有当集合为空(countAsync() === 0)时才插入七条示例任务,避免每次重启服务端都重复灌数据。

从源码看,insertAsync由 methods_async.js 中的_insertAsync实现:它会先校验参数,为文档生成_id(字符串或Mongo.ObjectID),然后通过this._collection.insertAsync(doc)真正写入数据库,并返回新文档的_id。所以上述代码等价于向tasks集合写入了七条形如{ _id: "...", text: "First Task" }的文档。

countAsync/fetchAsync等游标方法定义在 cursor.ts:countAsync会调用 MongoDB 驱动层的countDocuments;更值得注意的是,服务端游标上的同步方法count()会直接抛错,提示"请改用countAsync()"——这也是 Meteor 3 全面转向异步 API 的强制约束。

用 Solid 渲染集合数据

接下来是"有趣的部分":用 Solid 渲染任务列表。修改imports/ui/App.jsx

import { createSignal, For, Show } from "solid-js"; import { Meteor } from "meteor/meteor"; import { Tracker } from "meteor/tracker"; import { TasksCollection } from "../api/TasksCollection"; export const App = () => { const subscription = Meteor.subscribe("tasks"); const [isReady, setIsReady] = createSignal(subscription.ready()); const [tasks, setTasks] = createSignal([]); Tracker.autorun(async () => { setIsReady(subscription.ready()); setTasks(await TasksCollection.find().fetchAsync()); }); return ( <div class="container"> <header> <h1>Todo List</h1> </header> <Show when={isReady()} fallback={<div>Loading ...</div>} > <ul> <For each={tasks()}> {(task) => ( <li>{task.text}</li> )} </For> </ul> </Show> </div> ); };

这个组件把 Meteor 的响应式数据源与 Solid 的细粒度响应式原语结合了起来:

  • createSignal:Solid 的状态原语。isReady保存订阅就绪状态,tasks保存任务数组。
  • Meteor.subscribe("tasks"):订阅服务端的tasks发布,返回一个订阅句柄(subscription handle),其ready()方法表示订阅是否就绪。
  • Tracker.autorun:Meteor 的响应式追踪器。任何在函数体内被读取的响应式数据源(订阅状态、集合游标)发生变化时,这个函数都会自动重跑。从 tracker.js 的实现看,autorun会创建一个Tracker.Computation,收集被访问的Tracker.Dependency,数据变化时使计算失效并重跑。
  • TasksCollection.find().fetchAsync():客户端从 Minimongo 中异步取回全部文档。
  • <Show>/<For>:Solid 的控制流组件——Show根据isReady()决定显示列表还是Loading ...占位,For遍历tasks()渲染每个task.text

关键在于:当数据库数据变化时,Tracker.autorun会重新执行,setTasks更新 Signal,Solid 只精准更新受影响的 DOM 节点,无需手动刷新页面,也无需手动操作 DOM。

缺一不可:发布(Publish)数据到客户端

如果你现在运行应用,会发现列表是空的。原因在于:我们还没把数据发布到客户端。

这正是 Meteor 与传统 REST 架构的本质区别:Meteor 不需要 REST 调用,它依靠将服务端的 MongoDB 与客户端的 MiniMongoDB 进行同步来完成数据传输。流程是:先在服务端发布集合,再在客户端订阅它。

首先创建发布:

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

Meteor.publish接收两个参数:发布名称与发布函数。发布函数返回一个Collection.Cursor,Meteor 会把该游标对应的文档推送给每个订阅它的客户端。按 Meteor API 文档 所述,你还可以返回多个游标的数组,但数组中的游标必须来自不同的集合。

然后在服务端导入这个文件,让它真正生效:

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

最后一步,客户端订阅这个发布。其实在上一节我们已经在App.jsx里写好了:

... const subscription = Meteor.subscribe("tasks"); ...

订阅句柄的ready()状态与游标数据都在Tracker.autorun中被读取,因此整个数据链路是响应式的:服务端 MongoDB 数据一变,客户端 Minimongo 同步更新,Tracker.autorun重跑,Signal 更新,Solid 自动重渲染。你可以直接在服务端 MongoDB 里改数据,应用会实时响应并重新渲染,不需要刷新浏览器。

更多关于发布/订阅的细节,参见 Meteor API 文档中的 pub/sub 部分。

现在你的应用应该能显示七条任务了:

数据同步机制:MongoDB 与 MiniMongo

理解上面这套链路,关键在于 Meteor 的"双数据库"模型:

  • 服务端 MongoDB:真正的持久化数据库,存放所有数据。
  • 客户端 MiniMongo:浏览器内存中的精简版 MongoDB,缓存客户端订阅到的数据子集。

Meteor 通过 DDP(Distributed Data Protocol)协议在两者之间同步:服务端发布游标对应的文档变更(插入、更新、删除),客户端 Minimongo 维护本地缓存并触发Tracker依赖失效。这带来两个体验上的巨大优势:零 REST 样板代码实时更新——数据变更自动推送到所有订阅的客户端。

在实际项目中,发布函数通常会按需裁剪数据(例如只发布当前用户可见的任务、用projection排除敏感字段、根据this.userId做权限过滤),而不是像本例这样无脑find()全量返回。这属于服务端数据安全的核心实践。

检查数据库:meteor mongo 与 GUI 客户端

想要确认数据确实写进了 MongoDB,有两种方式:

方式一:命令行。在应用根目录的终端里运行:

meteor mongo

即可连接到 Meteor 为你启动的内嵌 MongoDB。默认情况下,内嵌 MongoDB 运行在3001 端口

方式二:GUI 客户端。使用 MongoDB 图形化客户端(如 NoSQLBooster)连接。连接信息如下:

连接成功后,你可以在左侧面板看到数据库列表:

双击tasks集合,就能看到我们插入的七条文档:

每份文档都包含 Meteor 自动生成的_id字段和我们在insertTask中写入的text字段。直接在这里修改文档内容,再切回浏览器,你会看到应用实时反映了改动。

小结

本步完成了 Meteor 集合从创建到渲染的完整闭环:

  1. 创建imports/api/TasksCollection.jsnew Mongo.Collection("tasks")
  2. 初始化server/main.js在启动时用insertAsync写入种子数据;
  3. 渲染App.jsx中用Tracker.autorun+ SolidcreateSignal/Show/For响应式渲染;
  4. 同步imports/api/TasksPublications.js发布 + 客户端Meteor.subscribe("tasks")订阅,MongoDB 与 MiniMongo 自动同步。

在下一步中,我们将创建任务表单,把用户输入的新任务写入集合,让 Todo 应用真正"活"起来。

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

【免费下载链接】meteor

Meteor, the JavaScript App Platform

项目地址:https://gitcode.com/gh_mirrors/me/meteor
点击查看免费下载
上一篇:实测!Hyperswitch支付吞吐量基准测试全指南:从环境搭建到性能调优
下一篇:PyQt多语言切换终极指南:QTranslator完整使用教程

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询