MV-01 前端基础
01 · 前端基础(Frontend Basics)
📅 预计 70 分钟 | ⭐ = 高频考点 | 📌 中英术语见文末
✍️ 配套练习:网页练习shengxia.dev/quiz?module=mv01
1.0 先给直觉:网页 = 房子
想象你要开一家店:HTML 是房子的骨架——墙有几面、门开在哪、房间怎么分,决定"有什么";CSS 是装修——墙刷什么颜色、门用什么材质、家具摆多宽,决定"长什么样";JavaScript 是店里的员工——有人推门就打招呼、点菜就下单、付款就找零,决定"怎么动"。
三者缺一不可:只有骨架的屋子没法住人,只装修没有员工的店不会营业,只有员工没房子就无处立足。前端开发,就是把这三件事配合好。
💡 记忆口诀:HTML 是骨头,CSS 是皮,JS 是大脑和四肢。
1.1 HTML:网页的骨架 ⭐
标签就是"积木"
HTML 用标签(tag)描述内容。一个标签通常成对出现:<标签名>内容</标签名>,前一个是开始标签,后一个是结束标签(多了个 /)。少数标签是自闭合的,比如图片 <img>。
<!-- 注释:浏览器不显示,只给人看 -->
<h1>标题:页面的大标题</h1> <!-- 一级标题 -->
<p>段落:一段普通文字</p> <!-- paragraph 段落 -->
<a href="https://shengxia.dev">链接</a> <!-- a = anchor 锚点,href 是目标地址 -->
<img src="logo.png" alt="网站logo"> <!-- img 图片,src 图片地址,alt 描述文字 -->
几个要点:
- 属性(attribute)写在开始标签里,格式是
属性名="值",如<a href="...">的href。 - 元素(element)= 开始标签 + 内容 + 结束标签,是 HTML 的基本组成单位。
- 标签可以嵌套:
<div>里放<p>,形成树状结构,称为 DOM 树。
页面基本结构
一个标准网页必须有文档声明和 html/head/body 三层结构:
<!DOCTYPE html> <!-- 告诉浏览器:这是现代 HTML 文档 -->
<html lang="zh-CN"> <!-- 根元素,lang 声明语言 -->
<head> <!-- 头部:放"给浏览器看"的配置信息 -->
<meta charset="UTF-8"> <!-- 字符编码,避免中文乱码 -->
<title>我的第一个页面</title> <!-- 浏览器标签页上显示的文字 -->
</head>
<body> <!-- 主体:放"给用户看"的所有内容 -->
<h1>欢迎</h1>
<p>这是正文。</p>
</body>
</html>
语义化:标签要"名正言顺"
不要所有内容都塞 <div>。用语义化标签(semantic tags)让结构有含义:<header> 页头、<nav> 导航、<main> 主内容、<footer> 页脚、<article> 文章。好处有两个:可读性好(人一看就懂结构),利于搜索引擎和辅助工具(屏幕阅读器能准确朗读)。这就像装修时把门牌写清楚,客人不用猜。
⚠️ 常见错误
- 标签忘记闭合:
<p>文字少了</p>,浏览器会自动"脑补",但嵌套会乱掉,后续样式容易出错。 - 乱嵌套:
<p><div>...</div></p>,块级元素套错,浏览器会悄悄拆开,结果和你预期不符。 <img>不写alt:图片加载失败时显示空白,屏幕阅读器也无法描述,可访问性差。<meta charset="UTF-8">缺失:中文直接显示成乱码。
1.2 CSS:给网页化妆 ⭐
选择器:找到要改装的元素
CSS 规则 = 选择器(selector)+ 声明块。选择器决定"改谁",声明决定"改成什么"。
/* 选择器 { 属性: 值; } */
h1 { /* 标签选择器:选中所有 <h1> */
color: #e8590c; /* 文字颜色:十六进制橙色 */
font-size: 28px; /* 字号:28 像素 */
}
.title { /* 类选择器:选中 class="title" 的元素,用 . 开头 */
color: #2b8a3e;
}
#logo { /* ID 选择器:选中 id="logo" 的元素,用 # 开头 */
width: 120px;
}
常用选择器:标签选择器 div、类选择器 .box(最常用,可复用)、ID 选择器 #header(唯一)、后代选择器 .nav a(.nav 里的 a)。优先级大致是 ID > 类 > 标签,记不住就用类选择器,最不容易踩坑。
盒模型:每个元素都是个盒子
每个元素都是一个盒子,从内到外四层:content(内容)→ padding(内边距)→ border(边框)→ margin(外边距)。
.card {
width: 300px;
padding: 20px; /* 内容与边框之间的空隙 */
border: 1px solid #ddd; /* 1 像素实线边框 */
margin: 10px auto; /* 上下 10px,左右自动居中 */
}
Flex 布局:一行摆平
想让一排元素横着排列、垂直居中,用 flex 最省事:
.nav {
display: flex; /* 开启弹性布局 */
justify-content: space-between; /* 主轴:两端对齐 */
align-items: center; /* 交叉轴:垂直居中 */
}
display: flex 开启后,子元素自动变成一行排列,justify-content 管水平分布,align-items 管垂直对齐。这是现代前端最常用的布局手段。
⚠️ 常见错误
- 类选择器忘记写
.:写title { ... },浏览器会当成"找<title>标签",样式不生效。 - 盒模型算错尺寸:
width: 300px+padding: 20px实际占 340px,因为默认 box-sizing 是 content-box。想要"宽就是宽",加box-sizing: border-box。 - 忘记写分号:
color: red后面没;,同一条规则后续的其他声明可能失效。 - ID 当类用:
id页面中必须唯一,给多个元素用同一个 id 会导致选择器错乱,复用请用class。
1.3 JavaScript:让页面动起来 ⭐
变量与函数
JS 是网页的编程语言。变量用 let 声明,函数用 function 定义:
let count = 0; // 声明一个可变的变量
const max = 10; // 声明常量,不能重新赋值
function addOne() { // 定义一个函数
count = count + 1; // 修改外部变量
console.log(count); // 在控制台打印,便于调试
}
addOne(); // 调用函数,count 变成 1
数组与对象
数组是有序列表,对象是"名值对"集合,两者是前端数据的主力:
const todos = ['买牛奶', '交房租']; // 数组,用 []
const user = { name: '小张', age: 20 }; // 对象,用 {}
todos.push('写作业'); // 向数组末尾追加
console.log(user.name); // 读取对象属性,输出: 小张
user.age = 21; // 修改对象属性
DOM:HTML 在 JS 眼中的样子
浏览器把 HTML 解析成一棵 DOM 树(Document Object Model),JS 通过操作这棵树来改变页面。最常用的两个"找人"方法:
const btn = document.querySelector('#submit'); // 按 CSS 选择器找第一个匹配元素
const list = document.querySelectorAll('li'); // 找到所有 <li>,返回列表
btn.textContent = '提交中...'; // 修改元素文本
btn.classList.add('disabled'); // 添加一个 CSS 类
在 JS 里修改了,页面立即变化——这是后面理解"数据驱动视图"的直觉起点:JS 是唯一能真正改变页面的角色。
⚠️ 常见错误
- 没等页面加载完就操作 DOM:
<script>放在<head>里时元素还不存在,querySelector返回 null 然后报错。解决办法:把<script>放到</body>前,或用DOMContentLoaded事件。 let和const混用:该用const的用let,代码意图不清晰;反过来用const声明了又要改,直接报错。- 字符串拼接混乱:
"我的名字" + name容易漏空格,模板字符串更稳:\我的名字是 ${name}``。 ==与===混淆:==会做类型转换(1 == "1"为 true),===要求类型也相同,写代码一律用===。
1.4 事件:让页面"听见"用户 ⭐
addEventListener:给元素"装耳朵"
事件(event)是用户与页面的交互信号:点击、输入、鼠标移动……用 addEventListener 给元素绑定处理函数:
<button id="btn">点我</button>
<p id="msg"></p>
const btn = document.querySelector('#btn');
const msg = document.querySelector('#msg');
btn.addEventListener('click', function () { // 监听 click 点击事件
msg.textContent = '按钮被点击了!';
});
事件对象与常用事件
处理函数会收到一个事件对象 event,里面有触发元素、坐标等信息:
btn.addEventListener('click', (event) => {
console.log(event.target); // 被点击的元素
console.log(event.type); // 事件类型,这里是 "click"
});
// 输入事件:input 事件在用户每次输入时触发
const input = document.querySelector('#name');
input.addEventListener('input', (event) => {
console.log(event.target.value); // 当前输入框里的内容
});
常用事件:click(点击)、input(输入)、change(失去焦点且值变化)、submit(表单提交)、keydown(按键)。箭头函数 (event) => {...} 是普通函数的简写形式,现在的主流写法。
表单提交:拦截默认行为
点提交按钮页面会刷新,用 preventDefault() 拦下来做自己的处理:
const form = document.querySelector('#form');
form.addEventListener('submit', (event) => {
event.preventDefault(); // 阻止默认的页面刷新
console.log('表单提交,但页面没刷新');
});
⚠️ 常见错误
addEventListener写错在 HTML 里:onclick="fn()"这种写法能跑但耦合度高、难维护,推荐统一用addEventListener。- 回调函数名带括号:
btn.addEventListener('click', fn())括号导致立即执行而非点击时执行,传fn不带括号。 - 忘记
preventDefault():表单提交后页面刷新,调试半天才发现状态全没了。 - 事件绑定在动态添加的元素上失效:后来才插入 DOM 的元素,不会自动拥有之前绑定的监听,需要绑定在它自己身上。
1.5 综合小案例:一个待办输入框
把前三节串起来,做一个"输入 → 点击 → 追加到列表"的小功能:
<input id="input" placeholder="输入内容">
<button id="btn">添加</button>
<ul id="list"></ul>
const input = document.querySelector('#input');
const btn = document.querySelector('#btn');
const list = document.querySelector('#list');
btn.addEventListener('click', () => {
const text = input.value.trim(); // 读取输入并去掉首尾空格
if (!text) return; // 空内容直接返回,不添加
const li = document.createElement('li'); // 创建一个 li 元素
li.textContent = text; // 填入文本
list.appendChild(li); // 挂到 <ul> 下
input.value = ''; // 清空输入框
});
这个案例的流程:找元素 → 绑定事件 → 读数据 → 改页面。注意一个关键动作——createElement 创建节点、appendChild 插入节点,这就是"用 JS 手动操作 DOM"的典型姿势。后面学 MVVM 时,你会发现框架帮你把这一步自动化了。
⚠️ 常见错误
- 用
input.value的时机不对:在点击事件里读,拿到的是最新值;在输入框外读,可能是空字符串。 trim()漏掉:用户只敲空格也算有内容,列表会多一条空白项。- 没有清空输入框:添加完用户还得手动删,体验差,代码也不够"闭环"。
1.6 CSS 布局进阶:让元素"站对位置"
水平居中
让块级元素在容器里水平居中,最常用的是 margin: 0 auto——左右外边距自动平分剩余空间:
.box {
width: 300px;
margin: 0 auto; /* 左右自动居中,前提是元素有确定宽度 */
}
文字居中则用 text-align: center;注意它管的是文字和行内元素,管不了块级元素本身。
垂直居中:flex 一招通吃
过去垂直居中要写不少"奇技淫巧",现在用 flex 最省心——父容器开启 flex,子元素自动居中:
.parent {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 200px; /* 父容器要有高度,才能算出"居中" */
}
只要记住这一组:父容器 display: flex + 两条对齐属性,几乎所有居中需求都能解决。
网格布局 Grid:二维"切豆腐"
flex 擅长一维(一行或一列)排列;grid 擅长二维(行列同时控制),像切豆腐一样把容器切成格子:
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 三列,每列等宽 */
gap: 12px; /* 格子间距 */
}
三列卡片、照片墙这类需求,grid 一行声明就搞定,子元素自动落进格子。
响应式:不同屏幕给不同样式
用**媒体查询(media query)**在屏幕宽度变化时切换样式,这是"响应式设计"的起点:
/* 默认样式:两列 */
.grid { grid-template-columns: 1fr 1fr; }
/* 屏幕宽度小于 600px 时:改成一列,更适合手机 */
@media (max-width: 600px) {
.grid { grid-template-columns: 1fr; }
}
先写默认样式,再用 @media 覆盖小屏幕的样式,手机和电脑都能获得合理布局。
⚠️ 常见错误
- 垂直居中忘给父容器高度:父元素没有高度时"居中"无从谈起,子元素还是从顶部开始。
text-align: center想居中块级元素:它只对文字/行内元素生效,块级元素要用margin: 0 auto或 flex。- 媒体查询写错断点:宽度条件写反、或覆盖顺序放错,小屏样式没生效,检查
max-width/min-width的方向。 - grid 和 flex 混用想当然:先问"这是一维还是二维布局",一维用 flex,二维用 grid。
1.7 开发者工具:前端调试的"三板斧"
浏览器控制台
按 F12 打开开发者工具,**Console(控制台)**是你最好的伙伴:
- 用
console.log()打印变量,确认数据是什么。 - 看到红色报错先读第一行,它指向出错的文件与行号。
- 报错信息里
xxx is not defined= 变量名拼错或没声明,Cannot read properties of null= 元素没找到。
console.log('当前值:', count); // 打印,观察运行过程
元素面板与 Styles
**Elements(元素)**面板可以选中页面元素,右侧直接看到它的 HTML 和所有 CSS 规则。想试一个样式效果,不用改代码——在面板里临时改,满意了再写进文件。这是排查"样式为什么不生效"的最快路径。
网络面板
**Network(网络)**面板列出页面所有请求。页面资源加载失败、接口报错时,看这里:红色项就是请求失败,点进去能看状态码(404 找不到、500 服务器错误)。它帮你区分"是前端写错,还是服务器那边的问题"。
⚠️ 常见错误
- 报错只截图最后一行:完整报错的第一行才指向问题位置,贴全报错更好排查。
- 样式不生效就瞎猜:用 Elements 面板看规则有没有被其他样式覆盖,或选择器有没有匹配上。
- 不看 Network 就说是前端 bug:资源 404、接口 500 都可能来自服务器或路径,先看请求结果再下结论。
📌 记忆口诀
- HTML / CSS / JS:骨头、皮、大脑,三件套各司其职。
- 盒模型:从里到外——内容、内边距、边框、外边距,四兄弟围成一圈。
- 选择器优先级:ID 最狠,类次之,标签最弱;写代码多用类。
- 改页面三连:
querySelector找人,addEventListener装耳朵,改属性就变。
📌 双语术语表(本讲)
| 中文 | English | 记忆点 |
|---|---|---|
| 标签 / 元素 | tag / element | 标签成对出现 |
| 属性 | attribute | 写在开始标签里 |
| 选择器 | selector | 找到要改的元素 |
| 盒模型 | box model | 内容/内边距/边框/外边距 |
| 弹性布局 | flexbox | display: flex |
| 文档对象模型 | DOM | HTML 的树形结构 |
| 变量 / 常量 | variable / constant | let / const |
| 数组 / 对象 | array / object | [] / {} |
| 事件 | event | 用户与页面的交互信号 |
| 事件对象 | event object | event.target |
| 节点 | node | DOM 树上的一个元素 |
⭐ 本讲考点清单
- HTML 基本结构:
<!DOCTYPE html>、<html>/<head>/<body> - 常见标签与属性:
a/href、img/src/alt、p、h1~h6 - 语义化标签的意义与常见用法
- 选择器:标签、类、ID、后代,优先级 ID > 类 > 标签
- 盒模型四层结构与
box-sizing: border-box - flex 布局:
display: flex+justify-content+align-items - JS 变量
let/const、函数、数组、对象基本语法 - DOM 操作:
querySelector、createElement、appendChild、textContent - 事件:
addEventListener、event.preventDefault()、常用事件类型 - 综合流程:找元素 → 绑事件 → 读数据 → 改页面