从 ”user-chat“ 项目看前后端分离、模块化与 DOM 编程

前言 :前后端分离是当代 Web 开发的主流架构,模块化是代码可维护性的基石,而一份好的 prompt 则是与 AI 协作的核心竞争力。本文以一个极简的 user-chat 项目为例,从前端三件套到后端 json-server,从 HTML 语义化标签到 Bootstrap CSS 框架,带你走一遍"手工搭建全栈项目"的完整链路。


目录

  1. 项目全景:前后端分离
  2. [前端三件套:HTML + CSS + JS](#前端三件套:HTML + CSS + JS "#%E5%89%8D%E7%AB%AF%E4%B8%89%E4%BB%B6%E5%A5%97html--css--js")
  3. 模块化设计思想
  4. [HTML 语义化与搜索引擎友好](#HTML 语义化与搜索引擎友好 "#html-%E8%AF%AD%E4%B9%89%E5%8C%96%E4%B8%8E%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E5%8F%8B%E5%A5%BD")
  5. [盒子模型与 DOM 编程](#盒子模型与 DOM 编程 "#%E7%9B%92%E5%AD%90%E6%A8%A1%E5%9E%8B%E4%B8%8E-dom-%E7%BC%96%E7%A8%8B")
  6. [Bootstrap CSS 框架:让页面好看](#Bootstrap CSS 框架:让页面好看 "#bootstrap-css-%E6%A1%86%E6%9E%B6%E8%AE%A9%E9%A1%B5%E9%9D%A2%E5%A5%BD%E7%9C%8B")
  7. [后端准备:json-server 快速搭建 API](#后端准备:json-server 快速搭建 API "#%E5%90%8E%E7%AB%AF%E5%87%86%E5%A4%87json-server-%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA-api")
  8. [Prompt 思考:AI 时代的高效协作](#Prompt 思考:AI 时代的高效协作 "#prompt-%E6%80%9D%E8%80%83ai-%E6%97%B6%E4%BB%A3%E7%9A%84%E9%AB%98%E6%95%88%E5%8D%8F%E4%BD%9C")
  9. 总结

项目全景:前后端分离

目录结构

bash 复制代码
user-chat/
├── fe/                  # 前端:专注 UI 与交互
│   ├── index.html       # 结构 + 样式引入
│   └── common.js        # DOM 编程 + 数据渲染
├── backend/             # 后端:专注数据与 API
│   ├── db.json          # 数据库(JSON 文件)
│   ├── package.json     # 后端项目描述
│   └── node_modules/    # 依赖(json-server 等)
└── readme.md            # 项目文档

为什么要前后端分离?

flowchart LR A["浏览器
HTML + CSS + JS"] -->|"HTTP 请求"| B["后端 API Server
json-server"] B -->|"JSON 数据"| A
维度 传统混写 前后端分离
职责 后端模板渲染 HTML 前端管页面,后端管数据
开发 前后端互相等待 前后端并行开发
复用 服务端代码难跨项目 API 可同时服务 Web / App / 小程序
维护 逻辑耦合在一起 定位 bug 清晰:前端 or 后端

在这个项目中,fe/ 目录和 backend/ 目录就是两个完全独立的"关注域":

  • 前端只看得到 HTML 页面,它不关心数据从哪里来------直接写死的数组也好,fetch 请求的 JSON 也好,对 DOM 渲染来说没有区别。
  • 后端只管提供数据json-server db.json 一行命令就把 JSON 文件变成了 RESTful API,前端可以用 fetch('/users') 来消费。

在实际的 OPC(One Person Company)模式下,一个人同时写前端和后端,分离架构让换脑成本降到最低------上午调 UI、下午调 API,互不干扰。


前端三件套:HTML + CSS + JS

代码骨架

fe/index.html 展示了一个标准 HTML5 页面的"三件套"组织方式:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- CSS 在头部引入:让样式更早加载,用户更快看到好看的页面 -->
    <link href="bootstrap.css" rel="stylesheet">
</head>
<body>
    <!-- HTML 负责结构 -->

    <!-- JS 在底部引入:等 DOM 树建好再执行 -->
    <script src="./common.js"></script>
</body>
</html>

三件套各自职责

技术 负责 在本项目中的体现
HTML 结构------页面有什么 headermaintablefooter
CSS 样式------页面长什么样 Bootstrap CDN + 行内思考(containerrowcol
JS 行为------页面能干什么 DOM 查询、动态插入 <tr>
flowchart TD A["HTML
骨架"] --> B["CSS
皮肤"] A --> C["JS
肌肉"] B --> D["用户看到的完整页面"] C --> D

一个小细节:CSS 放在 <head> 中、JS 放在 </body> 前。这是为了让样式尽早生效,用户打开页面的第一眼就是"美的",而 JS 不阻塞 DOM 树的构建。


模块化设计思想

什么是模块化?

模块化就是把代码按职责拆到不同的文件和目录,每个文件只做一件事。

flowchart TD subgraph 反模式 X["一个巨大的 app.js
包含所有逻辑"] end subgraph 模块化 Y1["fe/ 目录:前端专属"] Y2["backend/ 目录:后端专属"] Y3["common.js:DOM 渲染"] Y4["db.json:数据存储"] end X -->|"重构"| Y1 X -->|"重构"| Y2

为什么需要模块化?

问题 无模块化 有模块化
维护 改一个功能要翻几千行代码 定位到具体文件,直接改
扩展 加新功能怕动到旧逻辑 新功能 = 新文件,互不影响
优化 牵一发动全身 按需优化单个模块
协作 多人同时改一个文件 = 冲突地狱 各改各的目录,并行推进

本项目的模块划分

go 复制代码
fe/           → "我只管用户看到的东西"
  index.html  → "我只管结构骨架"
  common.js   → "我只管 DOM 操作和数据渲染"

backend/      → "我只管数据服务"
  db.json     → "我只管存数据"
  package.json → "我只管描述这个 Node 项目"

每个目录有明确的职责边界,每个文件只做一件事。这就是模块化的核心------把复杂问题拆成简单问题,再逐个击破


HTML 语义化与搜索引擎友好

不要 <div> 满天飞

HTML5 提供了丰富的语义化标签,每个标签自带"含义",让搜索引擎和辅助设备(如屏幕阅读器)能理解页面结构。

html 复制代码
<!-- ❌ 纯 div 堆砌:机器看不懂结构 -->
<div class="header">标题</div>
<div class="main">
  <div class="sidebar">侧栏</div>
  <div class="content">
    <div class="table">...</div>
  </div>
</div>
<div class="footer">底部</div>

<!-- ✅ 语义化标签:机器和人一眼看懂 -->
<header>标题</header>
<main>
  <aside>侧栏</aside>
  <table>
    <thead>...</thead>
    <tbody>...</tbody>
  </table>
</main>
<footer>底部</footer>

本项目使用的语义化标签

标签 语义 本项目位置
<header> 页头 / 导航区域 index.html:10
<main> 页面主体内容(一个页面仅一个) index.html:12
<aside> 侧边栏 / 补充内容 index.html:13
<footer> 页脚 / 版权信息 index.html:35
<table> + <thead> + <tbody> 数据表格 index.html:15-31

语义化 = SEO 友好

搜索引擎的爬虫在解析页面时,会利用语义标签来理解内容权重:

flowchart LR A["\
爬虫认为:核心内容"] --> B["加分"] C["\

爬虫认为:一个普通容器"] --> D["不加分"]
  • <main> 直接告诉爬虫"这是正文",<div class="main"> 需要爬虫"猜"。
  • <table> + <thead> + <tbody> 让爬虫识别出这是结构化数据,而非布局用的表格。
  • <header> / <footer> 帮助爬虫分清哪些是导航、哪些是脚注,不被噪音干扰。

通俗理解:你可以把语义标签想象成马路上画的箭头线和标识------不是你自己看的,而是让别人(搜索引擎)更容易读懂你的页面。


盒子模型与 DOM 编程

盒子模型

HTML 里默认有两类标签:

类型 默认行为 典型标签 比喻
块级元素 独占一行,可设宽高 <div> <header> <main> <p> <table> 盒子------搭骨架
行内元素 不换行,宽高由内容撑开 <span> <a> <img> <strong> 内容------填血肉

开发口诀:先写盒子,再写内容。

css 复制代码
/* Bootstrap 提供的 container 就是典型的"盒子"思路 */
.container {
  /* 中间内容宽度固定,左右留白 */
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}
flowchart TD A["盒子(块级)
container"] --> B["盒子(块级)
row"] B --> C["盒子(块级)
col"] C --> D["内容
table / 文字 / 图片"]

CSS 布局的三板斧

概念 作用 本项目示例
container 固定宽度 + 居中,适配不同屏幕 <main class="container">
row 一行,容纳列 <div class="row">
col 列,放在 row 里 <div class="col-md-6">

这套"容器 → 行 → 列"的布局模式从 PC 时代延续至今,解决了不同尺寸设备上内容对齐的经典问题。

DOM 编程

**DOM(Document Object Model)**是浏览器把 HTML 文本解析成 JS 可以操作的对象树。

flowchart TD A["document
(根节点)"] --> B["document.documentElement
\"] B --> C["document.head
\"] B --> D["document.body
\"] D --> E["header"] D --> F["main"] D --> G["footer"] F --> H["aside"] F --> I["div.row"] I --> J["table"] J --> K["thead"] J --> L["tbody"]

再看 common.js 里的 DOM 操作:

js 复制代码
// 1. 通过 CSS 选择器"穿越"DOM 树,定位到目标节点
const oBody = document.querySelector('.table tbody');

// 2. 数据驱动------遍历数组,动态生成 HTML 片段
for (let user of users) {
  oBody.innerHTML += `
    <tr>
      <td>${i}</td>
      <td>${user.name}</td>
      <td>${user.nickname}</td>
      <td>${user.hometown}</td>
    </tr>
  `;
}

核心三步:

  1. 查节点 --- document.querySelector() 从 HTML 页面"走进"JS 内存
  2. 改内容 --- .innerHTML 动态修改 DOM 节点的内部 HTML
  3. 数据驱动 --- 遍历 JS 数组,模板字符串拼出 HTML,渲染到页面

面试常考的"不用框架,手写一个数据渲染"就是这个思路。大厂特别注重这种底层能力------不依赖 React/Vue,用原生 JS 完成 DOM 操作。


Bootstrap CSS 框架:让页面好看

为什么聊 Bootstrap?

flowchart LR A["裸 HTML
白底黑字,无布局"] -->|"引入 Bootstrap"| B["Bootstrap 加持
栅格、表格样式、响应式"]

原生 HTML 像素颜,结构是对的但不好看。Bootstrap 是一套开箱即用的 CSS 样式库,Twitter 团队出品,解决的就是"后端程序员不会写 CSS"的痛点。

本项目如何引入

html 复制代码
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">

一行 CDN 链接,不需要 npm install,不需要构建工具,加载即用。

本项目使用的 Bootstrap 特性

class 作用 效果
container 固定宽度容器,居中 内容不会撑满全屏,左右有留白
row 弹性行 内部的 col 按 12 列栅格排布
col-md-6 占 6/12 = 一半宽度 中等屏幕以上占半行
col-md-offset-3 向右偏移 3/12 让表格居中显示
table Bootstrap 表格基础样式 带边框、间距的表格
table-striped 斑马条纹 奇数行和偶数行颜色交替

Bootstrap 的核心设计:12 列栅格系统

flowchart TD A["屏幕宽度"] --> B["12 等分"] B --> C["col-md-6 = 占 6 份
(50% 宽度)"] B --> D["col-md-4 = 占 4 份
(33% 宽度)"] B --> E["col-md-3 = 占 3 份
(25% 宽度)"]

这套栅格系统让布局从"靠感觉微调"变成了"靠数字精确控制"------col-md-6 col-md-offset-3 翻译成人话就是"占半行,左右各空四分之一",无论屏幕多大都能保持居中。


后端准备:json-server 快速搭建 API

从零到 API 只需两步

bash 复制代码
# Step 1:初始化 Node 项目
npm init -y
# 生成 package.json ------ 后端项目的"身份证"

# Step 2:安装 json-server
npm i json-server
# 一个把 JSON 文件变成 RESTful API 的神器

package.json------后端项目的描述文件

json 复制代码
{
  "name": "backend",
  "version": "1.0.0",
  "scripts": {
    "dev": "json-server db.json"
  },
  "dependencies": {
    "json-server": "^1.0.0-beta.15"
  }
}
  • scripts.dev :定义了启动命令,npm run dev 一行启动整个后端。
  • dependencies :声明了项目依赖哪些第三方包,其他开发者 clone 代码后 npm install 即可还原环境。

db.json------以文件为数据库

json 复制代码
{
  "users": [
    { "id": 1, "name": "李宇刚", "hometown": "南昌", "nickname": "东理薛之谦" },
    { "id": 2, "name": "胡航",   "hometown": "南昌", "nickname": "航哥" },
    { "id": 3, "name": "赖庆庆", "hometown": "信丰", "nickname": "橙帅" }
  ]
}

一行 npm run dev 后,json-server 自动生成以下 API:

HTTP 方法 端点 说明
GET /users 获取所有用户
GET /users/1 获取 id=1 的用户
POST /users 新增用户
PUT /users/1 修改 id=1 的用户
DELETE /users/1 删除 id=1 的用户
flowchart LR A["db.json
JSON 文件"] -->|"json-server 启动"| B["RESTful API
http://localhost:3000"] C["前端 fetch()"] -->|"GET /users"| B B -->|"JSON 响应"| C

在这个项目中,前端目前用的是 common.js 里硬编码的数组。但架构上已经准备好了------一旦把数据源从常量数组切换为 fetch('/users'),就是标准的前后端分离应用。


Prompt 思考:AI 时代的高效协作

什么是 Prompt 思考?

Prompt 是你与 AI 之间的"需求文档"。写好 prompt,和写好代码需求一样重要------输入决定输出

flowchart LR A["模糊的 prompt
'帮我写个页面'"] --> B["AI 随便写
大概率不是你要的"] C["精确的 prompt
'写一个用户列表页
带 HTML 语义标签
引入 Bootstrap 表格
JS 动态渲染数据'"] --> D["AI 精准输出
一次到位"]

本项目 README 中的 Prompt 思维

Prompt 关键词 触达的知识点 本项目落点
"页面好看" Bootstrap CSS 框架 bootstrap.min.css CDN 引入 + 栅格系统
"结构良好 搜索引擎友好" HTML 语义化标签 <header> <main> <aside> <footer> <thead> <tbody>
"不要 div 满天飞" 块级元素做盒子,语义标签替代 div 整个 index.html 只用了一个 <div>

好 Prompt 的四个要素

  1. 给出上下文 --- "我正在做一个 user-chat 项目,前端三件套、后端 json-server"
  2. 明确技术栈 --- "用 Bootstrap 3 做样式,原生 JS 操作 DOM"
  3. 描述期望效果 --- "表格有斑马条纹、居中显示、数据动态渲染"
  4. 限定边界条件 --- "不要用 div 满天飞,用语义化标签"

一个反直觉的发现:你写得越"啰嗦"的 prompt,AI 写得越快越好。因为 AI 不是在"猜"你的意图------它是在执行你的规格说明。


总结

回顾这个 user-chat 项目,一条清晰的全栈开发链路浮出水面:

graph TD subgraph 架构层 A["前后端分离
fe/ vs backend/"] end subgraph 组织层 B["模块化
一个目录一个职责
一个文件一件事"] end subgraph 前端层 C["HTML 语义化
header/main/aside/footer/table"] D["CSS 框架
Bootstrap 栅格 + 表格"] E["DOM 编程
querySelector + innerHTML"] end subgraph 后端层 F["json-server
JSON 文件 → RESTful API"] end subgraph 协作层 G["Prompt 思考
精确的需求描述 → 高效的 AI 产出"] end A --> B B --> C B --> D B --> E A --> F C --> G D --> G
  1. 前后端分离是架构的骨架------前端管 UI,后端管数据,互不耦合。
  2. 模块化是代码的组织原则------每个目录有职责,每个文件做一件事。
  3. HTML 语义化是页面的"说明书"------让搜索引擎、辅助设备、其他开发者都能读懂你的意图。
  4. Bootstrap 是颜值的快捷键------一行 CDN 让页面从"能用"变"好看"。
  5. DOM 编程是前端的基本功------不依赖框架,用原生 JS 完成数据渲染。
  6. Prompt 思考是 AI 时代的核心技能------输入的质量决定了输出的质量。

最终建议:动手能力是最好的老师。打开 VS Code,照着这个项目结构,亲手写一遍 HTML + CSS + JS + json-server------当你看到数据从 JSON 文件一路"流"到浏览器页面的那一刻,前后端分离的概念就真正内化了。


相关推荐
星栈18 小时前
订单状态机别写散:我在 Rust CRM 里把 6 个状态收进领域模型
后端·rust·全栈
前端双越老师19 小时前
普通程序员有没有必要学习 Agent 开发?
前端·agent·全栈
AskHarries19 小时前
我如何从1000个产品里筛出方向
人工智能·产品·全栈
星栈2 天前
我在 Rust 全栈项目里用 JWT 做无状态认证
前端·后端·全栈
前端再部署2 天前
Nuxt3 AI Agent 控制台实战 15:公网试用前的访问控制、限频与模型开关
agent·全栈
Oo9203 天前
做一个用户列表页面,把模块化与语义化搞懂
javascript·全栈
Darling噜啦啦3 天前
从零搭建一个全栈项目:前后端分离 + DOM 动态渲染实战
javascript·全栈
浮生望3 天前
告别“散装代码”:一个前端学习者的首个“模块化”全栈项目实战
javascript·全栈
前端再部署4 天前
Nuxt3 AI Agent 控制台实战 14:接入真实大模型与 Tool Calling 执行链路
全栈