从 “手动搬砖“ 到 “自动施法“:界面开发的三次 “渡劫“ 升级记

📜 从 "一锅乱炖" 到 "各司其职":响应式驱动界面的诞生记

一、前言:开发界的 "进化论"

如果你问一个十年前的前端开发者:"今天改个列表数据要多久?" 他可能会翻出泛黄的记事本,告诉你需要先找后端改 Java 代码,再调 JSP 模板,最后用 jQuery 手动刷 DOM------ 整个过程像在解一团缠成麻花的耳机线🤯。

而现在,你只需要在 Vue 里改个users.value,界面就像被施了魔法一样自动更新。这种 "数据动,界面动" 的奇迹,可不是凭空掉下来的。今天咱们就扒一扒:响应式驱动界面到底是怎么从 "刀耕火种" 的年代,一步步进化到现在的 "智能时代" 的?顺便带大家围观几段 "祖传代码",看看每一步进化都藏着多少开发者的血泪史😂。

二、纯后端的套模板:"一锅乱炖" 的 MVC 时代

早年间的 Web 开发,简直是 "后端大厨" 包办全场。那时候流行的 MVC 模式,说好听点是 "分工明确",说难听点就是 "一锅乱炖"------ 后端同学既要管数据库查数据,又要写 HTML 模板,还要处理用户请求,活脱脱一个 "全能牛马"💼。

1.从server.js看后端的 "全能秀"

咱们先瞧瞧server.js里的操作:后端用 Node 的http模块搭了个服务器,然后干了件 "越界" 的事 ------ 自己写了个generateUserHTMl函数,把用户数据拼成了完整的 HTML 页面。这就像一个厨师不仅要炒菜,还要亲自摆盘、端菜,甚至帮客人擦桌子,忙得脚不沾地👨🍳。

代码展示:

复制代码
// node 服务器端代码
// node 内置的http 模块
// require 引入http 模块 node早期的commonjs
const http = require("http"); // commonjs
const url = require("url"); // url

// 数据
const users = [
    {
        id: 1,
        name: '张三',
        email: '123@qq.com'
    },
    {
        id: 2,
        name: '李四',
        email: '456@qq.com'
    },
    {
        id: 3,
        name: '王五',
        email: '789@qq.com'
    },
]
function generateUserHTMl(users) {
    const userRows = users.map(user =>
        `
        <tr>
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.email}</td>
        </tr>
        `
    ).join('');
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>User List</title>
        <style>
            table { width: 100%; border-collapse: collapse; margin-top: 20px; }
            th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
            th { background-color: #f4f4f4; }
        </style>
    </head>
    <body>
        <h1>Users</h1>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                </tr>
            </thead>
            <tbody>
                ${userRows}
            </tbody>
        </table>
    </body>
    </html>
    `
}
// req 用户请求
// res 响应对象
// http 是基于请求响应的简单协议
const server = http.createServer((req, res) => {
    const parsedUrl = url.parse(req.url, true);
    // console.log(parsedUrl);
    if (parsedUrl.pathname === '/'
        || parsedUrl.pathname === '/users') {
        res.statusCode = 200; // 响应头 状态码
        res.setHeader('Content-Type', 'text/html;chatset=utf-8');
        const html = generateUserHTMl(users);
        res.end(html);
    } else {
        res.statusCode = 404;
        res.setHeader('Content-Type', "text/plain")
        res.end('Not Found');
    }
})
// server 伺服状态
server.listen(1314, () => {
    console.log('Server is running on port 1314');
});

代码效果:

这里的 MVC 分工是这样的:

  • Model(数据层) :就是那个users数组,像菜市场的菜摊,存着张三、李四、王五三位同学的信息。
  • View(视图层) :藏在generateUserHTMl里的模板字符串,用${user.name}这种占位符把数据塞进去,后端程序员的键盘上,既要有写 SQL 的严谨,也要有调<td>标签的细腻。
  • Controller(控制层)createServer里的逻辑,收到/users请求后,先叫 Model 拿数据,再让 View 生成 HTML,最后通过res.end(html)扔给用户。

HTTP 伺服:

"HTTP 伺服" 通常指的是 "HTTP 服务器"(HTTP Server),是一种能够接收客户端(如浏览器)的 HTTP 请求,并通过 HTTP 协议返回相应资源(如网页、图片、数据等)的软件或程序。

它的核心功能是监听特定的网络端口,解析客户端发送的 HTTP 请求报文,处理请求(例如读取文件、调用后端程序等),然后生成 HTTP 响应报文并返回给客户端。

server.listen(1314)启动的服务,像个执着的服务员,死守 1314 端口,客人点啥就给啥,绝不问 "要不要加香菜"。

2.当年的开发日常:改个颜色要跨部门

那时候的前端开发者?不存在的!基本是后端开发者一边写 Java,一边调 CSS,最后还得用document.getElementById改页面。就像server.js里的逻辑:后端直接生成完整 HTML 返回,用户看到的每一个字,都是后端 "一手包办" 的。

这种模式最大的问题是:改个按钮颜色都要动后端代码!前端想加个动画?先跟后端商量能不能改模板;后端想优化数据库查询?可能不小心把前端的样式搞崩了。堪称 "牵一发而动全身" 的典范 ------ 就像给蛋糕裱花时,不小心把整个蛋糕扣在了地上🍰💥。

三、前后端分离:"鸳鸯锅" 式的革命

终于有一天,开发者们受不了了:"凭啥后端要管配色?凭啥前端要懂 SQL?" 于是,前后端分离像一场 "火锅革命" 降临了 ------ 清汤锅(前端)和红油锅(后端)彻底分开,各煮各的,互不干扰🍲!

1.前端:从 "被动接收" 到 "主动点菜"

前端终于有了自己的 "小厨房"(比如index.html)。以前是后端做好整盘菜端过来,现在前端自己搭好盘子(HTML 结构),然后主动去后端 "要食材":

复制代码
// 前端主动去后端"点菜"
<script>
    // 后端接口准备好了
    // DOM 编程
    fetch('http://localhost:3000/users')
        .then(res => res.json())
        .then(data => {
            console.log(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>

代码效果:

这段代码翻译成人话就是:"后端大哥,把用户数据给我呗~ 我自己会摆!" 数据从后端接口3000 获取,前端有了自己的 5500 端口,彻底实现 "住址独立"------ 就像孩子长大了,终于有了自己的房间,不用再跟爸妈挤一张床🛏️。

2.后端:从 "包办婚姻" 到 "专心搞生产"

后端终于可以扔掉 HTML 模板这个 "包袱" 了。它不再返回完整页面,只提供 "食材仓库"------ 也就是 API 接口(比如http://localhost:3000/users)。看看db.json里的结构,后端只需要把数据整理成 JSON 格式,前端要多少拿多少,不用管人家怎么炒。

db.json代码:

复制代码
{
    "users": [
        {
            "id": 1,
            "name": "张三",
            "email": "123@qq.com"
        },
        {
            "id": 2,
            "name": "李四",
            "email": "456@qq.com"
        },
        {
            "id": 3,
            "name": "王五",
            "email": "789@qq.com"
        }
    ]
}

这时候后端的日常变成:"今天接口响应速度快了 20ms,真棒!" 而不是:" 这个<tr>标签怎么又没闭合?"🎉

3.分离的快乐,但也有新的烦恼

前后端分离虽然解决了分工问题,但前端又掉进了 "DOM 操作" 的坑。看看index.html里的代码:拿到数据后,得先用querySelector找 tbody 节点,再用innerHTML重写内容。这就像买了菜回家,还得自己洗菜、切菜、洗碗 ------ 忙活半天,真正炒菜的时间没多少。

更坑的是,万一后续要加个 "删除用户" 功能,还得手动删数据、再手动删 DOM 节点,稍不注意就会出现 "数据删了但界面还在" 的灵异现象👻。前端开发者每天都在跟 DOM 打架:"这个节点怎么没找到?"" 为什么加了事件监听,一刷新就没了?"

四、响应式数据驱动:Vue 带我们进入 "自动驾驶" 时代

就在前端开发者被 DOM 折磨得快秃了的时候,Vue 带着 "响应式数据" 来了,直接把前端开发推进了 "自动驾驶" 时代✨。

代码展示:

复制代码
<script setup>
  import {
    ref, // 响应式api 将数据包装成响应式对象
    onMounted // 挂载
  } from 'vue'; 
  // 数据
  const users = ref([]);
  onMounted(() => {
    console.log('页面已经挂载完成');
    // 依然从 3000端口获取数据
    fetch('http://localhost:3000/users')
    .then(res => res.json())
    .then(data => {
      users.value = data;
    })
  })
</script>

<template>
<table>
  <thead>
    <tr>
      <th>id</th>
      <th>name</th>
      <th>email</th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="user in users" :key="user.id">
      <td>{{ user.id }}</td>
      <td>{{ user.name }}</td>
      <td>{{ user.email }}</td>
    </tr>
  </tbody>
</table>
</template>

<style scoped>

</style>

代码效果:

1.从App.vue看响应式的魔力

App.vue里,只需要用ref把数据 "包装" 一下:

复制代码
const users = ref([]); // 响应式数据,相当于给数据装了GPS

这一步看似简单,实则给数据装了个 "报警器"------ 只要users.value变了,Vue 就会立刻通知界面:"快!数据改了,赶紧更新!"

fetch拿到数据,只需要更新users.value = data,表格就会自动刷新。不用找节点,不用拼 HTML,数据一变,界面就像被遥控了一样跟着变。对比index.html里手动操作 DOM 的代码,简直是从 "骑自行车" 升级到了 "开特斯拉"🚗。

2.模板语法:写界面像填表格

Vue 的模板更是懒人福音。想循环渲染用户列表?一句v-for="user in users"搞定,比data.map().join('')优雅一百倍:

复制代码
<tr v-for="user in users" :key="user.id">
  <td>{{ user.id }}</td>
  <td>{{ user.name }}</td>
  <td>{{ user.email }}</td>
</tr>

这里的{``{ }}和后端模板的${ }很像,但本质不同:后端模板是 "一次性打印",数据变了要重新打印整个页面;而 Vue 的模板是 "智能局部更新",数据变了只改需要改的地方 ------ 就像改作文时,只涂掉错字,不用重写整篇文章✍️。

3.onMounted:等页面坐稳了再干活

App.vue里还有个贴心的onMounted钩子:

复制代码
onMounted(() => {
  // 页面挂载完成后再发请求
})

这就像快递员会等你到家了再送货,避免出现 "数据到了但页面还没准备好" 的尴尬 ------ 比index.html里直接在 script 里发请求靠谱多了,再也不用担心 "拿了数据却找不到地方放" 的窘境😌。

五、数据驱动界面:开发界的 "不变应万变"

从后端套模板到前后端分离,再到响应式驱动,其实一直在围绕一个核心进化 ------让数据成为界面的 "指挥棒"

后端套模板时,数据驱动的是服务器生成的 HTML(server.js里的generateUserHTMl);前后端分离时,数据驱动的是前端手动操作的 DOM(index.html里的innerHTML);而响应式框架里,数据直接驱动模板渲染(App.vue里的v-for)。变的是技术手段,不变的是 "数据优先" 的思想:只要数据对了,界面就一定对。

这种思想有多爽?想象一下:产品经理说 "列表要加个手机号字段",你只需要在db.json里加phoneApp.vue的模板里加<td>{``{ user.phone }}</td>,完事儿!不用改 CSS,不用调事件,甚至不用思考 DOM------ 这就是数据驱动的终极浪漫💖。

结语:响应式不是终点,是新起点

回顾这一路进化:从后端 "一锅乱炖" 的 MVC(server.js为证),到前后端 "各司其职" 的分离模式(index.html登场),再到 Vue"数据说了算" 的响应式驱动(App.vue封神),每一步都是为了让开发者少掉点头发,多做点有意义的事。

响应式驱动界面不是终点,它更像一个跳板 ------ 让我们从繁琐的 DOM 操作中解放出来,真正聚焦于业务逻辑和用户体验。未来可能还会有更智能的方式,但只要 "数据驱动" 这个核心不变,开发效率的提升就永远没有天花板。

相关推荐
by__csdn1 小时前
JavaScript性能优化实战:减少DOM操作全方位攻略
前端·javascript·vue.js·react.js·性能优化·typescript
Monly211 小时前
Vue:使用v-if v-else加载两个el-table 在切换时,会出现数据在家混乱 数据加载不全的情况
前端·javascript·vue.js
南知意-1 小时前
一个基于 Vue、Datav、Echart 框架开源免费的数据大屏可视化系统
前端·javascript·vue.js·开源软件·大屏项目
修己xj1 小时前
FlatNas:打造你的专属浏览器仪表盘,一个集优雅与实用于一身的开源导航页
前端
哆啦A梦15881 小时前
【vue实战】商城后台管理系统 03 首页-路由界面基础搭建
前端·javascript·vue.js
几何心凉1 小时前
小白上手代理网络,搭建自己的数据抓取工具
前端
蜗牛攻城狮1 小时前
ES6 Module 导入导出完全指南:语法、原理与最佳实践
前端·ecmascript·es6
张拭心8 小时前
Cursor 又偷偷更新,这个功能太实用:Visual Editor for Cursor Browser
前端·人工智能
I'm Jie8 小时前
深入了解 Vue 3 组件间通信机制
前端·javascript·vue.js