从后端拼模板到 Vue 响应式:一场前端界面的进化史
当开始学习前端开发时,很多人都会遇到一个共同的困惑:
为什么有的项目让后端直接返回 HTML?
为什么后来大家都开始使用 fetch 拉取 JSON?
而现在又流行 Vue 的响应式界面,几乎不再手动操作 DOM?
这些不同的方式看似杂乱,其实背后隐藏着一条非常清晰的技术发展路径。后端渲染 → 前端渲染 → 响应式渲染它们不是独立出现的,而是前端能力逐步增强、分工越来越明确后的必然产物。
1. 🌱 第一阶段:后端拼模板 ------ "厨师把菜做好端到你桌上"
让我们从你最初的 Node.js 服务器代码说起。
js
const http = require("http");// Node.js 内置模块,用于创建 HTTP 服务器或客户端
const url = require("url");// 用于解析 URL
const users = [
{ id: 1, name: '张三', email: '123@qq.com' },
{ id: 2, name: '李四', email: '1232@qq.com'},
{ id: 3, name: '王五', email: '121@qq.com' }
];
// 将 `users` 数组转换为 HTML 表格字符串
function generateUserHTML(users){
const userRows = users.map(user => `
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.email}</td>
</tr>
`).join('');
return `
<html>
<body>
<h1>Users</h1>
<table>
<tbody>${userRows}</tbody>
</table>
</body>
</html>
`;
}
// 创建一个 HTTP 服务器,传入请求处理函数
const server = http.createServer((req, res) => {
if(req.url === '/' || req.url === '/users'){
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end(generateUserHTML(users));
}
});
// 服务器监听本地 1314 端口。
server.listen(1314);
访问1314端口,得到的结果:
这段代码非常典型,体现了早期 Web 的模式:
- 用户访问
/users - 后端读取数据
- 后端拼出 HTML
- 后端把完整页面返回给浏览器
你可以把它理解成:
用户去餐馆点菜 → 厨房(后端)把菜做好 → 端到你桌上(浏览器)
整个过程中,浏览器不参与任何加工,它只是"展示已经做好的菜"。
🔍 后端拼模板的特点
| 特点 | 说明 |
|---|---|
| 后端掌控视图 | HTML 是后端生成的 |
| 数据和页面耦合在一起 | 改数据就要改 HTML 结构 |
| 刷新页面获取新数据 | 无法局部更新 |
| 用户体验一般 | 交互不够流畅 |
这种方式在早期 Web 非常普遍,就是典型的 MVC:
- M(Model): 数据
- V(View): HTML 模板
- C(Controller): 拼 HTML,返回给浏览器
"后端拼模板"就像饭店里:
- 厨师(后端)把所有食材(数据)做成菜(HTML)
- 顾客(浏览器)只能被动接受
这当然能吃饱,但吃得不灵活。
为了吃一个小菜,还要大厨重新做一桌菜!
这就导致页面每个小变化都得刷新整个页面。
2. 🌿 第二阶段:前后端分离 ------ "厨师只给食材,顾客自己配菜"
随着前端能力提升,人们发现:
让后端拼页面太麻烦了。
于是产生了 前后端分离。
🔸 后端从"做菜"变成"送食材"(只返回 JSON)
json
{
"users": [
{ "id": 1, "name": "张三", "email": "123@qq.com" },
{ "id": 2, "name": "李四", "email": "1232@qq.com" },
{ "id": 3, "name": "王五", "email": "121@qq.com" }
]
}
JSON Server 会把它变成一个 API:
bash
GET http://localhost:3000/users
访问该端口得到:

访问时返回纯数据,而不再返回 HTML。
🔸 前端浏览器接管"配菜"(JS 渲染 DOM)
html
<script>
fetch('http://localhost:3000/users')// 使用浏览器内置的 `fetch`() API 发起 HTTP 请求。
.then(res => res.json())// 解析响应为 JSON
// 渲染数据到页面
.then(data => {
const tbody = document.querySelector('tbody');
tbody.innerHTML = data.map(user => `
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.email}</td>
</tr>
`).join('');
});
</script>
浏览器自己:
- 发送 fetch 请求
- 拿到 JSON
- 用 JS 拼 HTML
- 填入页面

这就好比:
- 后端: 不做菜,只把干净的食材准备好(纯 JSON)
- 前端: 自己按照 UI 要求把菜炒出来(DOM 操作)
- 双方分工明确,互不干扰
这就是现代 Web 最主流的模式 ------ 前后端分离。
🚧 但问题来了:DOM 编程太痛苦了
你看这段代码:
html
tbody.innerHTML = data.map(user => `
<tr>...</tr>
`).join('');
是不是很像在手工组装乐高积木?
DOM 操作会遇到几个痛点:
- 代码又臭又长
- 更新数据要重新操作 DOM
- 状态多了之后难以维护
- 页面结构和业务逻辑混在一起
前端工程师开始苦恼:
有没有一种方式,让页面自动根据数据变化?
于是,Vue、React、Angular 出现了。
3. 🌳 第三阶段:Vue 响应式数据驱动 ------ "只要食材变化,餐盘自动变化"
Vue 的核心理念:
ref 响应式数据,将数据包装成响应式对象
界面由 {{}} v-for 进行数据驱动
专注于业务,数据的变化而不是 DOM
这是前端的终极模式 ------ 响应式渲染。
🔥 Vue 的思想
Vue 做了三件事:
- 把变量变成"会被追踪的数据"(ref / reactive)
- 把 HTML 变成"模板"(用 {{ }}、v-for)
- 让数据变化自动修改 DOM
你只需要像写伪代码一样描述业务:
vue3
<script setup>
import {
ref,
onMounted // 挂载之后
} from 'vue'
const users = ref([]);
// 在挂载后获取数据
onMounted(() =>{
fetch('http://localhost:3000/users')
.then(res => res.json())
.then(data => {
users.value = data;
})
})
</script>
而页面模板:
vue
<tr v-for="u in users" :key="u.id">
<td>{{ u.id }}</td>
<td>{{ u.name }}</td>
<td>{{ u.email }}</td>
</tr>
得到的结果为:
你不再需要:
- querySelector
- innerHTML
- DOM 操作
Vue 会自己完成这些工作。
如果 传统 DOM:
你要把所有食材手动摆到盘子里。
那么Vue:
你只需要放食材到盘子里(修改数据),
餐盘的摆盘会自动变化(界面自动更新)。
比如你修改了数组:
php
users.value.push({ id: 4, name: "新用户", email: "xxx@qq.com" });
页面会自动新增一行。
你删除:
ini
users.value.splice(1, 1);
页面自动少一行。
你完全不用动 DOM。
4. 🌲 三个阶段的对比
| 阶段 | 数据从哪里来? | 谁渲染界面? | 技术特征 |
|---|---|---|---|
| 1. 后端渲染(server.js) | 后端 | 后端拼 HTML | 模板字符串、MVC |
| 2. 前端渲染(index.html + db.json) | API / JSON | 前端 JS DOM | Fetch、innerHTML |
| 3. Vue 响应式渲染 | API / JSON | Vue 自动渲染 | ref、{{}}、v-for |
本质是渲染责任的迁移:
后端渲染 → 前端手动渲染 → 前端自动渲染
最终目标只有一个:
让开发者把时间花在业务逻辑,而不是重复性 DOM 操作上。
5. 🍁 为什么现代开发必须用前后端分离 + Vue?
最后,让我们用一句最通俗的话总结:
后端拼页面像"饭店厨师包办一切",效率低。
前端手动拼 DOM 像"自己做饭",累到爆。
Vue 像"智能厨房",你只需要准备食材(数据)。
Vue 的三大优势
1)极大减少开发成本
业务逻辑变简单:
ini
users.value = newUsers;
就够了,UI 自动更新。
2)更适合大型项目
- 组件化
- 模块化
- 状态集中管理
- 可维护性高
3)用户体验更好
- 页面不刷新
- 更新局部
- 响应迅速
6. 🌏 文章总结:从"厨房"看前端的进化历史
最终,我们回到开头的类比:
| 阶段 | 类比 |
|---|---|
| 第一阶段:后端拼模板 | 厨房(后端)做好所有菜,直接端给你 |
| 第二阶段:前端渲染 | 厨房只提供食材,你自己炒 |
| 第三阶段:Vue 响应式 | 智能厨房:只要食材变,菜自动做好 |
前端技术每一次进化,都围绕同一个核心目标:
让开发者更轻松,让用户体验更好。
而你上传的代码正好构成了一个完美的演示链路:
从最原始的后端拼模板,到 fetch DOM 渲染,再到 Vue 响应式渲染。
理解了这三步,你就理解了整个现代前端技术的发展脉络。