CS 教程 · 第 11 章

Web 开发基础

HTML / CSS / JavaScript 入门

网页是互联网的窗口,Web 开发是打开这扇窗的手艺。

从简单的静态页面到复杂的单页应用(SPA),Web 开发技术栈在近二十年经历了爆发式增长。本章从"前端三件套"讲到后端框架,帮你建立完整的 Web 开发知识体系。


11.1 前端三件套:HTML + CSS + JavaScript

每一个网页的底层都是这三个东西:

┌────────────────────────────────┐
│  HTML(结构)—— 骨架            │
│  "这是一个标题,那是一个按钮"    │
├────────────────────────────────┤
│  CSS(样式)—— 皮肤             │
│  "标题是红色的,按钮要有圆角"    │
├────────────────────────────────┤
│  JavaScript(行为)—— 肌肉      │
│  "点击按钮时弹出提示框"          │
└────────────────────────────────┘

HTML:网页骨架




    
    我的第一个网页


    
    

欢迎来到我的网站

这是一段介绍文字。

访问 Example 我的照片

语义化标签(HTML5):

页头(logo、导航)
主体内容
文章/独立内容块
内容分区
2026 · 糖糖
💡 语义化标签让搜索引擎和屏幕阅读器更好地理解页面结构,对 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 设计示例

# 后端: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 证书

本章小结


[⬅️ 上一章:10-数据库基础](./10-数据库基础.html) · [🏠 目录](./README.html) · [➡️ 下一章:12-Linux系统管理](./12-Linux系统管理.html)

Collaplex · 克拉普莱克斯 collaplex.me · 2026 浙ICP备2026080865号