ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vue.js+Node.js全栈开发教程:直接连接MongoDB

Vue.js+Node.js全栈开发教程:直接连接MongoDB 1. 从零跑通 Vue.js Node.js 直连 MongoDB 的最小全栈项目很多刚接触全栈的朋友会卡在一个地方前端页面写好了后端接口也写了但数据到底有没有真的进到 MongoDB心里没底。这篇就带你做一个最小可运行的项目Vue.js 负责前端展示和提交Node.js 用官方 mongodb 驱动直连 MongoDB不绕弯子跑完你就能看到数据从表单一路写进数据库再被读回页面。核心检索词先摆出来Vue.js 全栈开发、Node.js 直连 MongoDB、mongodb 驱动 CRUD。这套组合适合谁适合已经会一点 JavaScript、想搞明白前后端数据链路到底怎么串起来的入门者。不需要你先精通 TypeScript也不需要你先学一堆框架封装我们就用最朴素的写法把「前端发请求 → 后端收请求 → 驱动操作数据库 → 结果返回前端」这条链路走通。为什么强调「直连」因为很多人一上来就用 Mongoose模型、Schema、中间件一层套一层出了问题根本不知道是哪一层挂的。而 node-mongodb-native 这个官方驱动API 更贴近数据库本身你写的每一行都能对应到一次真实的数据库操作。等你把这条链路摸熟了再去用 Mongoose 或者别的 ORM心里就有底了。项目结构我建议这样简单清晰前后端分开放fullstack-mongo-demo/ ├── server/ │ ├── package.json │ ├── db.js │ └── app.js └── client/ ├── package.json ├── vite.config.js ├── index.html └── src/ ├── main.js └── App.vue后端只做三件事连数据库、暴露 CRUD 接口、返回 JSON。前端只做两件事调接口拿列表、提交表单新增数据。没有多余的东西跑通之后再往上加功能。依赖清单也很克制。后端需要express和mongodb前端用 Vite 起一个 Vue 项目需要vue和axios。版本不用太纠结装当前稳定版就行。下面进入具体操作。2. TaoToken 前置准备把模型调用和 Key 管理先理顺在写代码之前有个前置环节值得先处理掉你后面调试接口、让 AI 帮你补全 CRUD 路由、排查报错的时候会频繁用到模型对话和 API Key。与其每次到处翻不如先把 TaoToken 这边的入口理清楚。TaoToken 官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 这个地址后面不加 UTM 参数直接访问就行。你可以先注册登录然后在控制台里把 Key 建好。具体几个入口我按用途分一下模型对话入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 你调试接口遇到reading choices这类返回结构报错时可以在这里直接问把报错原文贴进去让它帮你判断是响应体解析问题还是请求根本没发出去。API Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 这里生成的 Key 就是你后面写进.env或者配置片段里的那个。注意 Key 只显示一次建完立刻复制存好。控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 可以看调用记录和额度情况。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面写了 Base URL 怎么填、请求头怎么带。如果你后面要长期做编码或者跑 Agent可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。Claude Code 相关的接入说明在 https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite Anthropic 兼容入口在 https://taotoken.net/anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentanthropicutm_campaignrewrite 。这里要提醒一句TaoToken 是模型调用和 Key 管理的入口不是用来替代你本地编辑器或者数据库工具的。MongoDB 还是装在你本机或者你用的云服务上Node.js 还是跑在你的终端里。两者是配合关系别搞混。把 Key 拿到手之后建议先放到一个临时环境变量里别硬编码进代码。后面第三节的配置片段里我会写清楚怎么放。这一步花不了几分钟但能让你后面调试顺畅很多。3. 可复制配置连接字符串、依赖清单与 CRUD 路由这一节是重点所有配置我都给成可以直接复制的形式。先建目录然后分别初始化前后端。后端初始化mkdir -p fullstack-mongo-demo/server cd fullstack-mongo-demo/server npm init -y npm install express mongodb dotenv前端用 Vite 起 Vue 项目cd .. npm create vitelatest client -- --template vue cd client npm install npm install axios后端package.json里建议加一个启动脚本方便后面直接npm run dev{ name: server, version: 1.0.0, type: module, scripts: { dev: node app.js }, dependencies: { dotenv: ^16.4.5, express: ^4.19.2, mongodb: ^6.8.0 } }注意type: module这一行它让你可以用import语法和前端保持一致少切换心智。如果你习惯 CommonJS把这一行去掉后面代码里的import换成require即可。连接字符串放在.env文件里别提交到仓库# server/.env MONGO_URImongodb://127.0.0.1:27017 MONGO_DBfullstack_demo PORT3000如果你用的是带账号密码的连接串格式是mongodb://用户名:密码主机:端口/?authSourceadmin具体以你的数据库实际配置为准。本地默认安装的 MongoDB 一般不需要账号密码用上面那个就行。数据库连接模块db.js// server/db.js import { MongoClient } from mongodb; import dotenv from dotenv; dotenv.config(); const uri process.env.MONGO_URI || mongodb://127.0.0.1:27017; const dbName process.env.MONGO_DB || fullstack_demo; const client new MongoClient(uri); let db; export async function connectDB() { await client.connect(); db client.db(dbName); console.log(MongoDB connected:, dbName); return db; } export function getDB() { if (!db) { throw new Error(Database not initialized. Call connectDB first.); } return db; } export async function closeDB() { await client.close(); }这里有个细节官方驱动每次操作完理论上要 close但在 Web 服务里我们不会每个请求都开关一次连接而是启动时连一次进程退出时关一次。这样性能更好也避免频繁开关带来的问题。closeDB留给进程退出钩子用。主服务app.js包含 CRUD 路由// server/app.js import express from express; import { connectDB, getDB, closeDB } from ./db.js; const app express(); app.use(express.json()); // 允许前端跨域访问 app.use((req, res, next) { res.header(Access-Control-Allow-Origin, *); res.header(Access-Control-Allow-Headers, Content-Type); res.header(Access-Control-Allow-Methods, GET,POST,PUT,DELETE); next(); }); // 查询全部 app.get(/api/students, async (req, res) { try { const list await getDB().collection(students).find().toArray(); res.json({ ok: true, data: list }); } catch (err) { res.status(500).json({ ok: false, message: err.message }); } }); // 新增一条 app.post(/api/students, async (req, res) { try { const { name, age } req.body; const result await getDB().collection(students).insertOne({ name, age }); res.json({ ok: true, insertedId: result.insertedId }); } catch (err) { res.status(500).json({ ok: false, message: err.message }); } }); // 更新一条 app.put(/api/students/:id, async (req, res) { try { const { ObjectId } await import(mongodb); const { name, age } req.body; const result await getDB().collection(students).updateOne( { _id: new ObjectId(req.params.id) }, { $set: { name, age } } ); res.json({ ok: true, modified: result.modifiedCount }); } catch (err) { res.status(500).json({ ok: false, message: err.message }); } }); // 删除一条 app.delete(/api/students/:id, async (req, res) { try { const { ObjectId } await import(mongodb); const result await getDB().collection(students).deleteOne( { _id: new ObjectId(req.params.id) } ); res.json({ ok: true, deleted: result.deletedCount }); } catch (err) { res.status(500).json({ ok: false, message: err.message }); } }); const PORT process.env.PORT || 3000; connectDB().then(() { app.listen(PORT, () { console.log(Server running at http://127.0.0.1:${PORT}); }); }); process.on(SIGINT, async () { await closeDB(); process.exit(0); });前端App.vue里做列表展示和新增表单!-- client/src/App.vue -- script setup import { ref, onMounted } from vue; import axios from axios; const API http://127.0.0.1:3000/api/students; const list ref([]); const name ref(); const age ref(); async function load() { const res await axios.get(API); list.value res.data.data; } async function add() { if (!name.value) return; await axios.post(API, { name: name.value, age: Number(age.value) }); name.value ; age.value ; await load(); } async function remove(id) { await axios.delete(${API}/${id}); await load(); } onMounted(load); /script template div stylepadding: 24px; font-family: sans-serif; h2学生列表/h2 div input v-modelname placeholder姓名 / input v-modelage placeholder年龄 / button clickadd新增/button /div ul li v-foritem in list :keyitem._id {{ item.name }} - {{ item.age }} button clickremove(item._id)删除/button /li /ul /div /template前端vite.config.js保持默认即可因为我们后端已经手动加了 CORS 头不需要代理。如果你不想加 CORS 头也可以在这里配 proxy但那样多一层配置入门阶段先用 CORS 更直观。到这里配置片段就齐了。Base URL、Key、Model ID 这三件套如果你要接模型辅助调试Base URL 填https://taotoken.net/apiKey 用你在 api-keys 页面建的那个Model ID 按文档里写的填。这三样在接入文档里都有对照表。4. 验证请求启动服务、调用接口、核对数据库写入配置写完了现在动手验证。分三步启动数据库、启动后端、启动前端然后看数据有没有真的落库。先确认 MongoDB 在跑。本地安装的话Linux/macOS 一般用mongod --dbpath /你的数据目录Windows 上如果是安装版服务通常自动起来了可以在服务列表里确认。也可以用mongosh连一下mongosh能进去就说明数据库正常。启动后端cd fullstack-mongo-demo/server npm run dev看到MongoDB connected: fullstack_demo和Server running at http://127.0.0.1:3000就对了。如果只看到后者没看到前者说明连接那步有问题去第五节排查。启动前端cd fullstack-mongo-demo/client npm run devVite 会给你一个本地地址一般是http://127.0.0.1:5173。打开浏览器你应该能看到「学生列表」标题和一个空列表。现在用命令行直接测后端接口先插一条curl -X POST http://127.0.0.1:3000/api/students \ -H Content-Type: application/json \ -d {name:jack,age:20}返回类似{ok:true,insertedId:...}就说明写入成功。再查一下curl http://127.0.0.1:3000/api/students应该能看到刚才那条 jack 的数据_id是 MongoDB 自动生成的 ObjectId。最关键的一步直接去数据库里核对确认不是接口在骗你。打开mongoshmongosh use fullstack_demo db.students.find()如果这里能看到 jack 那条记录说明数据链路是真的通了前端/curl → Express 路由 → mongodb 驱动 → MongoDB 落盘。这一步别跳过很多人只看接口返回就以为成功了结果数据库里根本没写进去。再回到浏览器页面刷新一下列表里应该出现 jack。然后在页面上新增一条比如「张三 / 22」提交后再去mongosh里db.students.find()能看到张三就说明前端到后端这条链路也通了。删除和更新也顺手测一下。页面上点删除再去数据库查记录没了用 curl 发 PUT 请求改名字数据库里对应字段变了。四个操作都验证过这个最小项目就算跑通了。5. 本篇常见报错排查401、local proxy failed、reading choices、OAuth跑的过程中大概率会遇到几个典型报错我按实际遇到的顺序列一下对照着看。报错一401 Unauthorized如果你在接模型辅助调试时看到 401通常是 Key 没带对或者带错了地方。检查请求头里Authorization是不是Bearer 你的Key中间有没有多余空格。Key 是不是从 api-keys 页面复制的完整串有没有复制到一半。另外确认 Base URL 填的是https://taotoken.net/api不是首页地址。401 基本就是认证信息的问题和你的 MongoDB 代码无关。报错二local proxy failed这个报错一般出现在你本地起了代理工具或者网络环境有拦截的时候。先检查你的终端环境变量里有没有HTTP_PROXY、HTTPS_PROXY这类设置有的话临时清掉再试unset HTTP_PROXY unset HTTPS_PROXY然后重新跑请求。如果你用的是某些 IDE 插件自带的代理配置也要去插件设置里关掉。这个报错和 MongoDB 连接本身没关系是请求发不出去。报错三reading choices 或 Cannot read properties of undefined (reading choices)这个报错说明你拿到的响应体结构和预期不一样。常见原因是请求根本没成功返回的是一个错误对象但代码里直接去读response.choices[0]就报 undefined。排查方法先把原始响应打印出来看response里到底有什么。如果是模型调用场景确认返回的是不是标准结构如果是你自己的接口检查res.json返回的字段名和前端读取的是否一致。我踩过的坑就是后端返回{ data: [...] }前端却读res.list结果就是 undefined。报错四OAuth 相关报错如果你在配置 Claude Code 或者某些 CLI 工具时看到 OAuth 报错先确认你用的是 API Key 方式还是 OAuth 方式。两者不能混。用 API Key 的话在配置里填 Base URL 和 Key 就行不要走 OAuth 流程。Claude Code 的接入说明在 https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite Anthropic 兼容入口在 https://taotoken.net/anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentanthropicutm_campaignrewrite 按文档里的方式配别自己猜。报错五MongoServerError: connect ECONNREFUSED 127.0.0.1:27017这个和上面几个不同是数据库没起来。确认mongod进程在跑端口是不是 27017.env里的MONGO_URI有没有写错。如果是 Docker 起的 MongoDB确认端口映射对不对。报错六ObjectId 转换失败更新和删除接口里用到了new ObjectId(req.params.id)如果传进来的 id 不是合法的 24 位十六进制字符串会抛错。前端传的时候确认用的是数据库返回的_id别自己拼。如果 id 来自 URL 参数先做个校验再转换。排查思路统一一下先看报错原文判断是网络层、认证层、还是数据层再用最小请求复现比如直接用 curl 打后端排除前端干扰最后去数据库核对确认操作到底有没有生效。这三步走下来大部分问题都能定位。6. 继续往下走把这条链路用起来项目跑通之后你可以在这个骨架上加东西。比如给列表加分页后端用find().skip().limit()加搜索用find({ name: /关键字/ })加字段校验在插入前判断 name 是否为空。这些都是在这个最小项目上自然长出来的。如果你想让 AI 帮你补全这些功能可以把当前的路由代码贴到模型对话里让它按同样的风格加一个分页接口。模型对话入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 把需求说清楚比如「基于现有 Express mongodb 驱动的写法加一个支持 page 和 pageSize 的查询接口返回总数和当前页数据」它给的代码基本能直接用。长期做编码或者跑 Agent 的话Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 可以看下额度方案。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到配置问题先翻这里。Key 管理和控制台分别在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。最后说个实用技巧每次改完后端代码别只刷新前端页面一定要去mongosh里db.students.find()看一眼。前端显示对了不代表数据库写对了数据库写对了才是真的对了。这个习惯能帮你省掉很多「明明页面显示了但数据丢了」的困惑。
返回列表