网页是互联网的窗口,Web 开发是打开这扇窗的手艺。
从简单的静态页面到复杂的单页应用(SPA),Web 开发技术栈在近二十年经历了爆发式增长。本章从"前端三件套"讲到后端框架,帮你建立完整的 Web 开发知识体系。
11.1 前端三件套:HTML + CSS + JavaScript
每一个网页的底层都是这三个东西:
┌────────────────────────────────┐
│ HTML(结构)—— 骨架 │
│ "这是一个标题,那是一个按钮" │
├────────────────────────────────┤
│ CSS(样式)—— 皮肤 │
│ "标题是红色的,按钮要有圆角" │
├────────────────────────────────┤
│ JavaScript(行为)—— 肌肉 │
│ "点击按钮时弹出提示框" │
└────────────────────────────────┘
HTML:网页骨架
我的第一个网页
欢迎来到我的网站
这是一段介绍文字。
访问 Example
语义化标签(HTML5):
页头(logo、导航)
主体内容
文章/独立内容块
内容分区
💡 语义化标签让搜索引擎和屏幕阅读器更好地理解页面结构,对 SEO 和可访问性至关重要。
CSS:美化外观
CSS 盒模型:
┌─────────────────────────────┐
│ margin (外边距) │
│ ┌─────────────────────┐ │
│ │ border (边框) │ │
│ │ ┌───────────────┐ │ │
│ │ │ padding (内边距)│ │ │
│ │ │ ┌─────────┐ │ │ │
│ │ │ │ content │ │ │ │
│ │ │ │ (内容) │ │ │ │
│ │ │ └─────────┘ │ │ │
│ │ └───────────────┘ │ │
│ └─────────────────────┘ │
└─────────────────────────────┘
width + padding + border + margin = 实际占用空间
Flexbox 布局(现代布局首选):
栏目一
栏目二
栏目三
JavaScript:赋予生命
JavaScript 是网页的编程语言,操作 DOM(文档对象模型)来动态改变页面。
11.2 DOM 操作
DOM(Document Object Model)将 HTML 文档表示为树形结构,JavaScript 可以任意操控它。
document
└── html
├── head
│ └── title
└── body
├── h1
├── p
└── button
JavaScript DOM API
// === 获取元素 ===
const title = document.getElementById('title'); // 按 ID
const buttons = document.getElementsByClassName('btn'); // 按类名(动态集合)
const links = document.getElementsByTagName('a'); // 按标签名
const card = document.querySelector('.card'); // CSS 选择器(单个)
const cards = document.querySelectorAll('.card'); // CSS 选择器(全部)
// === 修改内容 ===
title.textContent = '新的标题'; // 纯文本(安全,防 XSS)
title.innerHTML = '强调的标题'; // HTML(注意安全)
// === 修改样式 ===
card.style.backgroundColor = '#f0f0f0';
card.style.display = 'none'; // 隐藏
card.classList.add('active'); // 添加类
card.classList.remove('inactive'); // 移除类
card.classList.toggle('dark'); // 切换类
// === 创建和插入元素 ===
const newPara = document.createElement('p');
newPara.textContent = '这是动态添加的段落';
document.body.appendChild(newPara); // 添加到末尾
// === 事件监听 ===
const btn = document.querySelector('#submit-btn');
btn.addEventListener('click', (event) => {
event.preventDefault(); // 阻止默认行为(如表单提交)
console.log('按钮被点击了!');
});
// === 实际例子:待办事项(前端版)===
const input = document.querySelector('#todo-input');
const list = document.querySelector('#todo-list');
function addTodo() {
const text = input.value.trim();
if (!text) return;
const li = document.createElement('li');
li.innerHTML = `
${text}
`;
// 点击删除按钮
li.querySelector('.delete-btn').addEventListener('click', () => {
li.remove();
});
// 点击文字切换完成状态
li.querySelector('span').addEventListener('click', () => {
li.classList.toggle('completed');
});
list.appendChild(li);
input.value = ''; // 清空输入框
input.focus(); // 重新聚焦
}
异步编程:fetch API
// === 发送 HTTP 请求 ===
// GET 请求(获取数据)
async function loadUsers() {
try {
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const users = await response.json();
renderUserList(users);
} catch (error) {
console.error('加载失败:', error);
showError('无法加载用户列表');
}
}
// POST 请求(提交数据)
async function createUser(userData) {
const response = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData),
});
return response.json();
}
// 使用
createUser({ name: '张三', email: 'zhangsan@example.com' })
.then(user => console.log('创建成功:', user))
.catch(err => console.error('创建失败:', err));
11.3 响应式设计
响应式设计让网站在手机、平板、电脑上都显示良好。
核心三要素
1. viewport 设置:
2. 流体布局(用相对单位):
/* ❌ 固定宽度 */
.container { width: 960px; }
/* ✅ 流体宽度 */
.container {
max-width: 960px;
width: 90%;
margin: 0 auto;
}
/* ✅ 用 rem/em 替代 px */
h1 { font-size: 2rem; } /* 相对于根元素字体大小 */
p { font-size: 1rem; }
3. 媒体查询(Media Query):
/* 默认样式(移动优先) */
.container {
display: flex;
flex-direction: column; /* 纵向排列 */
}
/* 平板及以上 */
@media (min-width: 768px) {
.container {
flex-direction: row; /* 横向排列 */
}
}
/* 桌面端 */
@media (min-width: 1024px) {
.container {
max-width: 960px;
}
}
常用断点:
| 设备 | 宽度范围 | 断点 |
|---|---|---|
| 手机 | < 768px | 默认 |
| 平板 | 768px - 1024px | `@media (min-width: 768px)` |
| 桌面 | > 1024px | `@media (min-width: 1024px)` |
CSS Grid 布局
/* Grid 是二维布局,比 Flexbox 更适合复杂网格 */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
/* 自动填充,每个格子至少 250px,多余空间均分 */
gap: 16px;
}
.gallery img {
width: 100%;
height: 200px;
object-fit: cover; /* 图片裁切以填充 */
border-radius: 8px;
}
11.4 后端语言对比
| 语言 | 代表框架 | 特点 | 适合场景 |
|---|---|---|---|
| Python | Django, Flask, FastAPI | 开发快、库丰富 | 快速原型、数据分析、AI 服务 |
| Node.js | Express, Nest.js | 前后端同语言、高并发 I/O | 实时应用、API 网关 |
| Go | Gin, Echo, Fiber | 高性能、编译型、并发强 | 微服务、高并发 API |
| Java | Spring Boot | 生态庞大、企业级 | 大型企业应用 |
| PHP | Laravel | 简单、托管容易 | CMS、传统网站 |
Python 后端概览
# Flask 示例:最简单的 Web 服务
from flask import Flask, jsonify, request
app = Flask(__name__)
# 模拟数据库
users = [
{"id": 1, "name": "张三", "email": "zhangsan@example.com"},
{"id": 2, "name": "李四", "email": "lisi@example.com"},
]
@app.route('/')
def home():
return '欢迎访问 API
'
@app.route('/api/users', methods=['GET'])
def get_users():
return jsonify(users)
@app.route('/api/users/', methods=['GET'])
def get_user(user_id):
user = next((u for u in users if u['id'] == user_id), None)
if user:
return jsonify(user)
return jsonify({"error": "用户不存在"}), 404
@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
new_user = {
"id": len(users) + 1,
"name": data.get('name'),
"email": data.get('email')
}
users.append(new_user)
return jsonify(new_user), 201
if __name__ == '__main__':
app.run(debug=True, port=5000)
Node.js 后端概览
// Express 示例
const express = require('express');
const app = express();
app.use(express.json());
let users = [
{ id: 1, name: '张三', email: 'zhangsan@example.com' },
{ id: 2, name: '李四', email: 'lisi@example.com' },
];
// 获取所有用户
app.get('/api/users', (req, res) => {
res.json(users);
});
// 获取单个用户
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
user ? res.json(user) : res.status(404).json({ error: '用户不存在' });
});
// 创建用户
app.post('/api/users', (req, res) => {
const newUser = {
id: users.length + 1,
name: req.body.name,
email: req.body.email,
};
users.push(newUser);
res.status(201).json(newUser);
});
app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));
11.5 框架概念:Flask vs Express
它们做了什么?
原生 HTTP 服务器(麻烦):
解析 HTTP 请求头 → 解析 URL → 路由分发 → 处理请求
→ 设置响应头 → 序列化数据 → 发送响应
框架帮你做了(你只写业务逻辑):
@app.route('/api/users') ← 框架处理路由
def get_users(): ← 你只写这里的逻辑
return jsonify(users) ← 框架处理序列化和响应
框架的核心组件
框架的典型结构:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 路由 │ │ 中间件 │ │ 请求/ │ │ 模板 │
│ Router │ │Middleware │ │ 响应处理 │ │ 引擎 │
│ /api/xxx │ │ 认证/日志 │ │ Req/Res │ │ Template │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │
└──────────────┴──────────────┴──────────────┘
│
┌──────────┐
│ ORM │ ← 数据库抽象层
│ SQLAlchemy│
└──────────┘
中间件(Middleware)
# Flask 中间件示例
from flask import Flask, request
import time
app = Flask(__name__)
@app.before_request
def log_request():
"""每个请求前执行:记录日志"""
print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {request.method} {request.path}")
@app.before_request
def check_auth():
"""每个请求前执行:检查认证"""
# 跳过登录接口
if request.path == '/api/login':
return
token = request.headers.get('Authorization')
if not token:
return {"error": "未认证"}, 401
// Express 中间件示例
const express = require('express');
const app = express();
// 应用级中间件:记录请求时间
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next(); // 调用 next() 继续处理
});
// 路由级中间件:需要认证的接口
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: '未认证' });
}
next();
};
// 只在特定路由使用中间件
app.get('/api/admin/users', authMiddleware, (req, res) => {
res.json({ message: '管理后台数据' });
});
11.6 前后端分离架构
传统模式 vs 前后端分离
传统模式(服务端渲染):
浏览器 ← 完整 HTML 页面 ← 服务器(模板渲染)
前后端分离:
浏览器(前端 SPA) ← JSON 数据 ← 后端 API
│
└── 独立部署的前端项目(React/Vue/Angular)
前后端分离的优势
┌──────────────────────────────────────────┐
│ CDN / Nginx │
│ 静态资源:index.html, JS, CSS │
└──────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ 前端应用 │ │ 后端 API │
│ React / Vue │───>│ Flask/Express/ │
│ (独立部署) │API │ Gin/FastAPI │
└─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ 数据库 │
│ PostgreSQL/MySQL │
└─────────────────┘
好处:
- 前后端独立开发、独立部署
- 同一个 API 服务 Web、iOS、Android 多个客户端
- 技术选型灵活(前端换框架不影响后端)
- 职责清晰,团队协作效率高
API 设计示例
# 后端:FastAPI 示例(现代 Python 框架)
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS:允许前端跨域访问
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # 前端地址
allow_methods=["*"],
allow_headers=["*"],
)
# 数据模型
class UserCreate(BaseModel):
name: str
email: str
class UserResponse(BaseModel):
id: int
name: str
email: str
# 模拟数据库
users_db = {}
@app.get("/api/users", response_model=list[UserResponse])
def list_users():
return list(users_db.values())
@app.post("/api/users", response_model=UserResponse, status_code=201)
def create_user(user: UserCreate):
user_id = len(users_db) + 1
new_user = UserResponse(id=user_id, **user.model_dump())
users_db[user_id] = new_user
return new_user
@app.get("/api/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
return users_db[user_id]
// 前端:调用后端 API
async function fetchUsers() {
const res = await fetch('http://localhost:8000/api/users');
return res.json();
}
async function createUser(name, email) {
const res = await fetch('http://localhost:8000/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, email }),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.detail);
}
return res.json();
}
11.7 Web 开发完整流程
1. 需求分析
└→ 用户故事、功能列表
2. 原型设计
└→ Figma / 纸笔画线框图
3. 前端开发
├→ HTML 搭建页面结构
├→ CSS (Flexbox/Grid) 布局和样式
├→ JavaScript 交互逻辑
└→ 调用后端 API 获取数据
4. 后端开发
├→ 设计数据库表结构
├→ 编写 API 接口
├→ 业务逻辑处理
└→ 数据库操作(CRUD)
5. 联调测试
└→ 前后端对接,修复问题
6. 部署上线
├→ 前端:构建 → CDN/Nginx
├→ 后端:服务器部署
├→ 数据库:迁移脚本
└→ 域名 + HTTPS 证书
本章小结
- HTML 是骨架、CSS 是皮肤、JavaScript 是肌肉,三者构成前端基础
- DOM 操作让 JavaScript 动态修改页面内容
- 响应式设计(流体布局 + 媒体查询 + Flexbox/Grid)适配多端
- 后端框架封装路由、中间件、请求处理,让你专注业务逻辑
- 前后端分离是现代 Web 开发的主流架构
- Flask/Express 轻量灵活,FastAPI/Gin 性能突出,选择取决于项目需求
[⬅️ 上一章:10-数据库基础](./10-数据库基础.html) · [🏠 目录](./README.html) · [➡️ 下一章:12-Linux系统管理](./12-Linux系统管理.html)