AIGC标识 通俗前端与后端

路由

🏗️ 对照 1:构建工具(Webpack vs Node 运行时)

前端脚手架(Vue CLI / Vite)给你最大的错觉是:代码保存 = 页面刷新。但后端完全不是这样。

维度 Vue + Webpack 项目 Node.js 后端项目
运行时间 构建时npm run build 打包完就结束了) + 浏览器运行时(代码跑在用户电脑上) 服务运行时node index.js 后进程一直在内存里跑,直到你 Ctrl+C)
热更新原理 Webpack Dev Server 监听文件变动 → 重新编译 Bundle → 浏览器通过 WS 接受到新模块替换(不重启进程 Nodemon 监听文件变动 → 杀掉旧进程重启整个 Node 进程(因为后端状态在内存里,不重启没法换)
核心任务 .vue 文件编译成 .js.css 启动一个 TCP 服务,死循环监听 3000 端口
类比 像“印刷厂”(把源码印成网页) 像“24小时营业的柜台”(一直在那等着接客)

关键认知差:你平时 npm run serve 启动的那个东西,严格来说是个静态文件服务器(让浏览器能访问到编译后的 JS)。而我们现在写的 Node,是业务逻辑服务器(处理登录、查数据库)。它们是两码事,甚至可以同时跑在不同的端口上。


🧭 对照 2:路由控制(Vue Router vs Express Router)—— 这是最迷惑的地方

两者写法极像,但触发的时机返回的内容天差地别。

// 【前端】Vue Router 写法
const routes = [
  { path: '/user/:id', component: UserProfile }
]
// 浏览器地址栏变成 /user/123 → 渲染 UserProfile 组件(不刷新页面)

// 【后端】Express 写法
app.get('/user/:id', (req, res) => {
  res.json({ id: req.params.id })
})
// 前端 fetch('/user/123') → 返回 JSON 数据(没有页面,没有样式)

我画个流程图,对比同一个 URL /user/123 在两边的待遇:

graph TB subgraph "前端Vue项目" A1["浏览器地址变化"] --> A2{"Vue Router 拦截"} A2 --> A3["匹配组件 UserProfile"] A3 --> A4["调用 render 函数"] A4 --> A5["📄 输出: DOM 节点 / 页面片段"] end
graph TB subgraph "后端Node项目" B1["fetch请求到达 3000端口"] --> B2{"Express 路由匹配"} B2 --> B3["执行 (req,res) => 函数"] B3 --> B4["查询数据库 / 处理逻辑"] B4 --> B5["📦 输出: JSON 字符串"] end
对比维度 Vue Router (前端) Express (后端)
谁在控制 浏览器内存中的 JS 代码 服务器硬盘里运行的 Node 进程
匹配后干嘛 渲染 Vue 组件,操作 DOM 执行一段函数(查库、读写文件)
返回内容 HTML 标签(用户直接看到) 数据(通常是 JSON,前端拿到后自己去渲染 DOM)
页面刷新吗 不刷新(SPA 精髓,无感切换) 不涉及页面(只是数据接口,跟页面跳转无关)

一句话总结Vue 路由 = “翻书”(翻到哪一页,展示哪一页的内容);Express 路由 = “问答题机器”(你问一个问题,它回答一段数据,不关心你用什么本子记下来)。


📦 对照 3:输出产物(dist 文件夹 vs 服务器接口)

前端脚手架最终产出 dist/index.html 和各种 chunk.js,而 Node 后端产出的是 “对请求的实时响应”

前端输出 后端输出
一堆静态文件(.js, .css, .ico) 一个持续运行的服务进程(没有 .exe 文件,就是那堆代码在内存里跑)
部署方式:扔到 Nginx / CDN 上 部署方式:node index.jspm2 start index.js
用户访问:输入网址 → 下载全部 JS → 浏览器渲染 用户访问:前端代码里 fetch 调用 → 拿到 JSON → 前端自己渲染

数据库


🧠 核心思想 1:数据库 = “不会丢失的全局变量”

你在 Vue 里写 const users = ref([]),数据存在浏览器内存里。刷新页面 → 数据清零

数据库干的第一件事:把这份数据从“内存”搬到“硬盘”里存起来。Node 进程重启、服务器断电,数据依然在。

前端概念 后端数据库概念 核心区别
const state = { users: [] } 数据库文件 (dev.db) 前者关机丢,后者关机还在
state.users.push(newUser) INSERT INTO users ... 前者改内存,后者改硬盘文件
state.users.find(u => u.id === 1) SELECT * FROM users WHERE id = 1 前者遍历数组,后者用算法快速查
页面刷新后要重新请求接口 服务重启后数据依然在 持久化是数据库的命根子

记住:你写的 prisma.user.create(),本质上就是 state.users.push(),只不过它把这条记录写进了硬盘上的 .db 文件,而不是只留在内存里。


🗂️ 核心思想 2:表 (Table) = 数组,行 (Row) = 对象

你前端经常这么写数据:

// 前端 JS 数组 + 对象
const users = [
  { id: 1, name: '小王', email: 'x@w.com', age: 25 },
  { id: 2, name: '小李', email: 'l@w.com', age: 30 }
];

数据库里长这样(二维表格,极其像 Excel)

id name email age
1 小王 x@w.com 25
2 小李 l@w.com 30

对照关系

  • 表名 (Table) = 数组名 (users)
  • 行 (Row / Record) = 数组里的每一个对象 ({ id: 1, name: '小王' })
  • 列 (Column / Field) = 对象里的每一个键 (name, email)

颠覆认知:你在前端操作数组用 mapfilterfind;在后端操作数据库,就是把同样的逻辑翻译成 SQL 语句,或者用 Prisma 这种“翻译官”帮你把 JS 语法转成 SQL。


🧩 核心思想 3:CRUD = 数组的增删改查(附对照翻译表)

这是你最熟悉的 4 个操作,我直接把“前端数组写法”和“后端数据库写法”逐行对标

操作 前端 JS (操作内存数组) 后端 SQL / Prisma (操作硬盘文件)
C (增) users.push({ id:3, name:'小王' }) prisma.user.create({ data: { name:'小王' } })
R (查) users.find(u => u.id === 1) prisma.user.findUnique({ where: { id:1 } })
U (改) users[0].name = '老王' prisma.user.update({ where:{id:1}, data:{name:'老王'} })
D (删) users.filter(u => u.id !== 1) prisma.user.delete({ where:{id:1} })

灵魂翻译:你平时写 users.find(u => u.id === 1) 是遍历数组找东西;数据库做同样的事,但它不需要遍历整个文件,而是用索引(Index) 直接定位,所以查几百万条数据也很快——这个你暂时不用深究,知道“数据库自带快速查找能力”就行。


posted @ 2026-08-05 22:52  需要成长的小哥  阅读(19)  评论(0)    收藏  举报