前后端模块化分离,web盒子布局思维

前言

我是一名刚入门的程序员,最近写了一个"用户聊天"小项目(user-chat)。项目虽小,但把前后端模块化分离的完整流程走了一遍。

一、项目总览:前后端各管各的

先看整个项目的目录结构:

go 复制代码
user-chat/
├── fe/                  ← 前端只碰这个目录
│   ├── index.html       ← 页面结构 + 样式引入
│   └── common.js        ← 页面交互逻辑
├── backend/             ← 后端只碰这个目录
│   ├── db.json          ← 数据源
│   ├── package.json     ← 后端项目描述文件
│   └── package-lock.json
└── readme.md

核心理念:每个文件夹有明确的职责划分,每个文件只做一件事。

  • fe/ 目录:专注前端,只管页面长什么样、用户怎么交互
  • backend/ 目录:专注后端,只管数据存哪里、接口怎么提供

前后端各司其职,互不干扰,通过 HTTP 接口沟通。这就像一个餐厅------前端是大堂服务员(接待客人、展示菜单),后端是后厨(准备食材、做菜),中间通过"订单小票"(HTTP 请求)来传递信息。

为什么不能把所有代码塞进一个文件?

如果代码、功能全堆在一起,会出现三个致命问题:

  • 不好维护:改一个样式要找半天,牵一发而动全身
  • 不好扩展:加一个新功能时,生怕把旧功能改坏了
  • 不好优化:代码像一团乱麻,根本不知道从哪下手

解决方案就是模块化拆分------职责分离之后,每个文件只做一件事,就像乐高积木,可以随意组合、替换、扩展。

二、前端内部也做了"再分离":三件套各司其职

打开 fe/index.html,前端本身也把结构、样式、行为三者做了分离:

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="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <!-- HTML 标签:负责结构 -->
    <header>1111</header>
    <main class="container">
        ...
    </main>
    <footer>222</footer>
    <!-- JS 在底部引入:负责行为 -->
    <script src="./common.js"></script>
</body>
</html>

CSS 放在 <head>、JS 放在 <body> 底部------这不是随意放的,而是有讲究的:

技术 作用 类比 引入位置 原因
HTML 负责结构 房子的钢筋骨架 整个文件 所有内容的载体
CSS 负责样式 房子的装修 <head> 尽早加载,让用户第一眼就看到好看的页面,体验更好
JS 负责行为 房子的水电系统 <body> 底部 等页面结构渲染完了再加载,不阻塞页面显示

CSS 框架:Bootstrap

你可能注意到了,这个项目没有手写一行 CSS------全靠引入的 Bootstrap 框架:

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

Bootstrap 是 Twitter 开源的 CSS 框架,帮我们准备好了大量开箱即用的样式。对于新手来说,先用框架快速出效果,后面再深入学习 CSS 原理,是高效的学习路径。

三、CSS 布局的三个核心概念

1. Box(盒子模型)------"先写盒子,再写内容"

在 CSS 的世界里,所有可见元素都是矩形盒子。比如代码中的:

html 复制代码
<div class="row col-md-6 col-md-offset-3">
    <table class="table table-striped" id="user-table">
        ...
    </table>
</div>

外层 div 是一个大盒子(容器),里面的 table 是一个小盒子(内容)。布局的思维就是:先规划盒子套盒子的层级关系,再往盒子里填充具体内容。

2. Container(容器)------"中间固定,左右留白"

html 复制代码
<main class="container">

container 是 Bootstrap 提供的布局类,作用是:内容区域的宽度固定,左右两侧自动留白。这样无论用户用的是大屏幕台式机还是小屏幕笔记本,内容始终居中显示------这是从 PC 时代就积累下来的经典布局方案。

3. Row 和 Col(行列布局)------栅格系统

ini 复制代码
row = 一行
col = 一列

Bootstrap 把一行划分为 12 个等份 ,通过 col-md-数字 来控制元素占据的宽度:

html 复制代码
<div class="row col-md-6 col-md-offset-3">
  • col-md-6:占 6 份(即一行的一半宽度)
  • col-md-offset-3:向右偏移 3 份(从而实现居中效果)

这就是栅格系统------实现响应式布局的基石。

四、HTML 世界的两种标签类型

HTML 默认只有两大类标签,理解这个是写出好页面的第一步:

类型 核心特点 用来干什么 例子
块级元素 默认独占一整行 做"盒子",搭建页面骨架 divheaderfootermainasidetable
行内元素 兄弟之间可以排在同一行,互不干扰 装"内容"(文字、链接、图片) spanaimgem

代码中就能看到这个规律:

  • headermainfooterasidedivtable → 都是块级元素,用来搭骨架
  • 这些大盒子里再嵌套内容(文字、表格数据)

语义化标签:拒绝 div 满天飞

新手很容易写成这样:

html 复制代码
<div class="header">头部</div>
<div class="main">内容</div>
<div class="footer">底部</div>

全是 div,虽然也能跑,但就像一本书没有目录、没有章节标题------机器难以理解页面结构,搜索引擎爬虫和屏幕阅读器(视障用户依赖的工具)更是无从下手。

这个项目用了更规范的做法------语义化标签

html 复制代码
<header>头部</header>    ← 比 <div class="header"> 更有语义
<main>主体内容</main>     ← 比 <div class="main"> 更有语义
<footer>底部</footer>     ← 比 <div class="footer"> 更有语义
<aside>侧边栏</aside>     ← 比 <div class="sidebar"> 更有语义

这些标签和 div 同属块级元素,但名字本身就表达了含义 ------header 就是页头,footer 就是页脚,对人、对机器都更友好。大厂面试经常会问语义化标签,因为这是 Web 标准理解深度的直接体现。

Table 的语义化关键:thead + tbody

html 复制代码
<table class="table table-striped" id="user-table">
    <tbody>
        <tr>
            <td>ID</td>
            <td>姓名</td>
            <td>昵称</td>
            <td>家乡</td>
        </tr>
    </tbody>
</table>

thead(表头)和 tbody(表体)是表格语义化的关键结构。它们告诉浏览器哪些行是表头、哪些行是数据,这对表格的排序、筛选、打印、无障碍访问都至关重要。千万不要省略。

五、<!DOCTYPE html> 和 HTML 文档的本质

两种文本类型

浏览器处理两种文本:

类型 说明
text/plain 纯文本,记事本打开什么样就显示什么样
text/html HTML 标签文本,通过 HTTP 协议传输,由浏览器解析成可视化页面

你的 HTML 文件属于 text/html 类型,浏览器收到后会解析标签、渲染出可视化的网页。

<!DOCTYPE html> 是干嘛的?

html 复制代码
<!DOCTYPE html>

这行的作用是告诉浏览器:请用最新的 HTML5 标准渲染这个页面。如果不写,浏览器会进入"怪异模式"(向后兼容老版本 HTML4 的渲染方式),可能导致样式错乱、布局异常。每个正经的 HTML 文档,第一行一定长这样。

六、DOM 编程:JS 如何动态操控页面

这是前端最核心的底层能力,也是大厂面试的重点考察方向。

DOM 是什么?

DOM = Document Object Model(文档对象模型)

浏览器加载 HTML 后,会把每个 HTML 标签变成 JS 内存中的对象 ,并组织成一棵树状结构

xml 复制代码
document                              ← 文档对象(整个页面在 JS 中的入口)
  └── document.documentElement        ← 根节点(对应 <html> 标签)
        └── document.body             ← 页面主体(对应 <body> 标签)
              ├── <header>
              ├── <main>
              │     ├── <aside>
              │     └── <div class="row">
              │           └── <table id="user-table">
              │                 └── <tbody>
              │                       └── <tr> x N
              └── <footer>

你可以通过 document.querySelector() 在这棵树上旅行,找到任意节点,然后查看它的子节点、兄弟节点,甚至把它挂载到另一个节点上。

实际代码解读

打开 fe/common.js

js 复制代码
// 1. 准备一个空数组,用来存放从后端拿到的数据
let users = [];

// 2. 向后端发起 HTTP 请求
fetch('http://localhost:3000/users')
    .then(data => data.json())    // 3. 把响应体转成 JSON 格式
    .then(data => {
        console.log(data);        // 4. 打印看看拿到了什么
        users = data;             // 5. 存到 users 数组中

        // 6. 在 DOM 树上找到表格的 tbody 节点
        const oBody = document.querySelector("#user-table tbody");

        // 7. 遍历数据,动态插入 HTML
        for (let user of users) {
            oBody.innerHTML += `
                <tr>
                    <td>1</td>
                    <td>${user.name}</td>
                    <td>${user.nickname}</td>
                    <td>${user.hometown}</td>
                </tr>
            `;
        }
    });

这段代码展示了完整的数据驱动页面流程:

  1. 后端 JSON 数据 →
  2. 前端 fetch 请求 →
  3. document.querySelector() 找到挂载点 →
  4. .innerHTML 动态修改 DOM 内容 →
  5. 浏览器自动重新渲染 →
  6. 用户看到最新数据

传统的静态页面是"后端返回什么,页面就显示什么",而这种动态方式让前端自己掌控渲染------拿到数据后,JS 操控 DOM 来更新页面,不需要刷新整个页面,这就是现代 Web 应用的基础模式。

补充:for...of 语法

代码中遍历用户数组用的是 ES6 的新循环:

js 复制代码
for (let user of users) {
    // user 就是当前遍历到的那个用户对象
}

老式写法需要手动计数:

js 复制代码
for (let i = 0; i < users.length; i++) {
    let user = users[i];
}

for...of 不需要计数器,可读性更好,是现代 JS 的推荐写法。

七、后端:用 json-server 快速搭建数据接口

从零初始化一个后端项目

进入 backend/ 目录,第一条命令:

bash 复制代码
npm init -y

这会生成 package.json,它是后端项目的身份证

json 复制代码
{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "json-server --watch db.json"
  },
  "type": "commonjs",
  "dependencies": {
    "json-server": "^1.0.0-beta.15"
  }
}
  • name / version:项目名和版本号
  • scripts:定义启动命令,npm run dev 就是执行 json-server --watch db.json
  • dependencies:项目依赖了哪些第三方包,这里只有 json-server
  • type: "commonjs":使用 CommonJS 模块规范(Node.js 的传统方式)

安装 json-server

bash 复制代码
npm i json-server

json-server 是一个神器------它可以把一个 JSON 文件直接变成 HTTP 接口服务。对于学习阶段来说,不用学数据库、不用写 SQL、不用搭 Express,一个 JSON 文件就能跑起来。

数据文件 db.json

json 复制代码
{
    "users": [
        {
            "id": 1,
            "name": "张三",
            "hometown": "华夏",
            "nickname": "龙傲天"
        },
        {
            "id": 2,
            "name": "曹老板",
            "hometown": "梵蒂冈",
            "nickname": "梨花"
        },
        {
            "id": 3,
            "name": "niko",
            "hometown": "波黑尼亚",
            "nickname": "donk"
        }
    ]
}

一个普通的 JSON 对象字面量,users 数组里存放了三条用户记录,每条记录包含 idnamehometownnickname 四个字段。

json-server 会自动把这个结构映射为 RESTful 接口:

接口地址 方法 作用
http://localhost:3000/users GET 获取所有用户
http://localhost:3000/users/1 GET 获取 id=1 的用户
http://localhost:3000/users POST 新增一个用户
http://localhost:3000/users/1 DELETE 删除 id=1 的用户

零配置,直接能用------这就是 json-server 的价值。

启动后端服务

bash 复制代码
npm run dev

执行后,json-server 会监听 localhost:3000,前端就能通过 fetch 请求拿到数据了。--watch 参数表示它会监听 db.json 的文件变化,数据改了接口自动同步,开发体验极佳。

八、前后端联通:完整数据流一览

把整个过程串起来,数据是这样流动的:

bash 复制代码
┌─────────────────────────────────────────────────────────┐
│  backend/db.json                                         │
│  { "users": [...] }                                      │
│       │                                                  │
│       ▼                                                  │
│  json-server --watch db.json                             │
│  启动 HTTP 服务 → http://localhost:3000/users             │
│       │                                                  │
│       │  HTTP 请求(前端 fetch)                           │
│       ▼                                                  │
│  fe/common.js                                            │
│  fetch('http://localhost:3000/users')                    │
│       │                                                  │
│       ▼                                                  │
│  data.json()  →  遍历数据  →  querySelector 找挂载点        │
│       │                                                  │
│       ▼                                                  │
│  innerHTML += 动态拼接 <tr> 标签                           │
│       │                                                  │
│       ▼                                                  │
│  浏览器重新渲染 → 用户看到表格中的用户数据                     │
└─────────────────────────────────────────────────────────┘

前后端通过 HTTP 接口 沟通,各管各的------前端不关心数据怎么存的,后端不关心页面怎么渲染。这就是前后端分离的核心思想。

九、总结

这个小项目虽然简单,但它涵盖了现代 Web 开发最重要的几个基础思维:

思想 具体体现
目录级分离 fe/ 管前端,backend/ 管后端,职责清晰
前端再分离 HTML 管结构、CSS 管样式、JS 管行为,三者各司其职
盒子布局思维 先规划盒子套盒子的层级关系,再填充内容
语义化思维 header/main/footer/aside 代替 div 满天飞
DOM 编程思维 理解 JS 如何在内存中操控页面元素树
接口通信思维 前端通过 fetch 请求后端 HTTP 接口,数据驱动页面

对于我来说,理解这些思想比记住具体代码重要得多。

相关推荐
程序员牛奶1 小时前
[Algo-3]前缀和秒杀两道区间求和题:一维 + 二维统一模板
后端·算法
前端繁华如梦1 小时前
不写模型文件,用代码「捏」出 3D 世界:Vue3 + Three.js 程序化资产生成实战
前端·vue.js
BileiX1 小时前
CC-Switch的安装与使用
后端
灰子学技术1 小时前
Envoy OAuth2 过滤器功能实现分析
运维·服务器·前端·网络
覆东流1 小时前
Python变量与数值类型
开发语言·后端·python
程序员cxuan1 小时前
Codex 官方:/goal 的正确打开方式
人工智能·后端·程序员
雨辰AI1 小时前
人大金仓慢 SQL 根治方法论:问题定位 - 分析 - 优化全流程
数据库·后端·sql·mysql·政务
LCG元1 小时前
MySQL慢查询分析与索引调优:从故障诊断到性能翻倍的进阶之路
android·前端·mysql
天涯明月19931 小时前
后端工程师全栈转型前端入门
前端·状态模式·全栈工程师