写前端最忌“边写样式边调JS”。正确的流程是“内容优先 → 结构语义化 → 样式分离 → 交互增强”。请严格按以下 6 步执行:
抛开设计稿,先用纯文本列出页面所有内容和逻辑层级。
💡 HTML的本质是文档结构,不是视觉还原。只用原生标签表达结构,不加任何class/id/style,确保无CSS也可读。
💡 好的HTML自带SEO和无障碍访问能力。定义颜色、字体、间距等CSS变量,统一设计语言。
💡 先定规则再写组件,避免后期大量覆盖。用Flex/Grid实现小屏布局,再用min-width媒体查询扩展大屏。
💡 Mobile First不是口号,是减少代码量的最佳实践。在HTML/CSS完全可用后,再用JS添加动态行为,做好降级兜底。
💡 JS挂了页面还能用,才是合格的前端。检查兼容性、Core Web Vitals、无障碍评分,修复问题后再上线。
💡 自己觉得好用不算数,用户设备跑得快才算数。HTML结构 → CSS选择器优先级 → 盒模型 → JS控制台报错 → 网络请求 逐层排查。
目标:掌握语义化标签、表单、多媒体及无障碍基础。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文章详情页</title>
</head>
<body>
<header>
<nav aria-label="主导航">...</nav>
</header>
<main>
<article>
<h1>理解HTML语义化</h1>
<time datetime="2024-12-01">2024年12月1日</time>
<p>语义化不只是SEO...</p>
<figure>
<img src="diagram.webp" alt="语义化标签层级关系图" loading="lazy">
<figcaption>图1:常用语义化标签嵌套关系</figcaption>
</figure>
</article>
<aside aria-label="相关文章">...</aside>
</main>
<footer>© 2024 前端教程</footer>
</body>
</html>
| ❌ 避免使用 | ✅ 推荐替代 | 语义价值 |
|---|---|---|
| <div class="header"> | <header> | 明确标识页头区域 |
| <div class="nav"> | <nav> | 屏幕阅读器可快速跳转导航 |
| <b> / <i> | <strong> / <em> | 传达语气强调而非单纯样式 |
| <div class="btn"> | <button> | 自带键盘焦点和回车触发 |
| <a href="#" onclick> | <button> | 非跳转行为不应使用锚点 |
目标:掌握Flex/Grid布局、CSS变量、响应式设计模式。
:root {
/* 颜色系统 */
--color-primary: #264de4;
--color-text: #1e293b;
--color-bg: #ffffff;
/* 间距系统 (4px基准) */
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 2rem; /* 32px */
/* 字体系统 */
--font-body: system-ui, -apple-system, sans-serif;
--font-mono: 'Fira Code', monospace;
}
/* 暗色主题一键切换 */
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e2e8f0;
--color-bg: #0f172a;
}
}
| 场景 | 推荐方案 | 关键属性 |
|---|---|---|
| 单行/单列元素排列 | Flexbox | justify-content, align-items, gap |
| 二维网格布局 | CSS Grid | grid-template-columns/rows, area |
| 等高卡片列表 | Grid + auto-fill | repeat(auto-fill, minmax(280px, 1fr)) |
| 垂直居中 | Flex / Grid均可 | place-items: center |
| 圣杯/双飞翼布局 | Grid | grid-template-areas 命名区域 |
/* Mobile First: 默认样式为手机 */
.card-grid { display: grid; gap: var(--space-md); }
/* ≥640px 平板 */
@media (min-width: 640px) {
.card-grid { grid-template-columns: repeat(2, 1fr); }
}
/* ≥1024px 桌面 */
@media (min-width: 1024px) {
.card-grid { grid-template-columns: repeat(3, 1fr); }
}
/* ≥1280px 大屏 */
@media (min-width: 1280px) {
.card-grid { grid-template-columns: repeat(4, 1fr); }
}
目标:掌握现代JS语法、异步编程、模块化。
// 解构 + 默认值 + 剩余参数
const { name, age = 18, ...rest } = user;
const [first, ...others] = items;
// 可选链 + 空值合并
const city = user?.address?.city ?? '未知城市';
// 模板字面量
const greeting = `你好${name},今年${age}岁`;
// Promise.allSettled(比all更安全)
const results = await Promise.allSettled([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments')
]);
results.forEach(r => {
if (r.status === 'fulfilled') console.log(r.value);
else console.error(r.reason);
});
// utils/format.js
export function formatCurrency(amount) {
return new Intl.NumberFormat('zh-CN', {
style: 'currency', currency: 'CNY'
}).format(amount);
}
// components/Card.js
import { formatCurrency } from '../utils/format.js';
export class Card {
constructor(data) { this.data = data; }
render() {
return `<div class="card">
<h3>${this.data.title}</h3>
<p>${formatCurrency(this.data.price)}</p>
</div>`;
}
}
// main.js
import { Card } from './components/Card.js';
const card = new Card({ title: '课程', price: 299 });
document.getElementById('app').innerHTML = card.render();
目标:高效操作DOM、事件委托、Web API应用。
// ❌ 循环中逐个插入(触发N次重排)
items.forEach(item => {
const li = document.createElement('li');
li.textContent = item.name;
list.appendChild(li);
});
// ✅ DocumentFragment批量插入(只触发1次重排)
const fragment = document.createDocumentFragment();
items.forEach(item => {
const li = document.createElement('li');
li.textContent = item.name;
fragment.appendChild(li);
});
list.appendChild(fragment);
// ✅ 或使用模板字符串 + innerHTML(适合一次性渲染)
list.innerHTML = items.map(item =>
`<li data-id="${item.id}">${item.name}</li>`
).join('');
// ❌ 给每个按钮绑定事件(100个按钮=100个监听器)
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', handleDelete);
});
// ✅ 事件委托(1个监听器处理所有按钮)
document.querySelector('.todo-list').addEventListener('click', (e) => {
const deleteBtn = e.target.closest('.delete-btn');
if (!deleteBtn) return; // 点击的不是删除按钮则忽略
const id = deleteBtn.dataset.id;
deleteTodo(id);
deleteBtn.closest('li').remove();
});
| API | 用途 | 示例 |
|---|---|---|
| IntersectionObserver | 懒加载/滚动触发动画 | 图片进入视口时才加载 |
| ResizeObserver | 监听元素尺寸变化 | 容器查询的JS版 |
| MutationObserver | 监听DOM树变更 | 第三方插件注入内容检测 |
| Clipboard API | 读写剪贴板 | 一键复制代码块 |
| localStorage/sessionStorage | 本地持久化存储 | 记住用户偏好/购物车 |
| 指标 | 目标值 | 优化手段 |
|---|---|---|
| LCP (最大内容绘制) | ≤ 2.5s | 图片预加载、CDN、服务端渲染、字体优化 |
| INP (交互到下次绘制) | ≤ 200ms | 防抖节流、Web Worker、避免长任务 |
| CLS (累积布局偏移) | ≤ 0.1 | 图片/广告预留尺寸、字体FOIT/FOUT处理 |
# 推荐技术栈(2024+)
构建工具: Vite (开发秒启,Rollup生产打包)
代码规范: ESLint flat config + Prettier
类型安全: TypeScript (strict mode)
CSS方案: Tailwind CSS / CSS Modules / Vanilla Extract
测试: Vitest + Playwright (E2E)
部署: Vercel / Cloudflare Pages / Netlify
监控: Sentry + Web Vitals SDK
import() 动态导入路由级组件| 领域 | 核心关键词 | 重点掌握内容 |
|---|---|---|
| HTML | 语义化, 无障碍 | 结构化标签, ARIA, 表单验证, SEO基础 |
| CSS | 布局, 响应式 | Flex/Grid, CSS变量, 媒体查询, BEM命名 |
| JS语法 | ES6+, 异步 | 解构/展开, Promise/async, 模块化, 闭包 |
| DOM | 事件, 性能 | 事件委托, Fragment, Observer API, 防抖节流 |
| 工程化 | 构建, 优化 | Vite, TypeScript, Core Web Vitals, CI/CD |