HTML、CSS、JavaScript 与 Vue:从零到一的知识结构

前端的学习路径有一个独特的问题:每个知识点单独学都不难,但把它们组装成一个能跑的应用时,脑子里的知识是散的。这篇文章的目的是帮你建立一套从 HTML 到 Vue 的连贯认知,知道每个技术在前端体系里的位置,以及工作中真正用到的是什么。

HTML:内容的骨架

HTML 不是编程语言。它是一个声明式的文档格式——告诉浏览器”这里有个标题”、”这里是个按钮”,浏览器负责把它们画出来。

你真正需要掌握的就三件事:

文档流。块级元素(divsectionp)独占一行;行内元素(spana)跟在同一行。理解这个区别是理解一切 CSS 布局的前提。之后学 Flexbox 和 Grid,本质上是在改变默认的文档流行为。

语义化。用 <header><nav><main><article> 而不是一律 <div class="xxx">。不只是为了 SEO,更实际的好处是你的代码结构一眼就能看懂。

表单<form><input><select><button> 这些是工作中打交道最多的标签。原生的表单验证(requiredpatterntype="email")能省不少 JS 代码。

HTML 本身不会是你学习的瓶颈。花一个下午过一遍 MDN 的 HTML 元素参考,知道有哪些标签就够了。真正花时间的在 CSS。

CSS:布局和样式的现实

盒模型

浏览器把每个元素看作一个矩形盒子,由内到外依次是 content、padding、border、margin。

标准盒模型中,width 只作用于 content 区域。设置 width: 200px; padding: 20px; 之后,元素实际占用的水平空间是 242px(200 + 40 内边距 + 2 边框)。

box-sizing: border-boxwidth 的含义改成”从 border 到 border”,包含 content、padding 和 border。这是目前几乎所有项目都会在全局样式中设置的属性:

1
2
3
*, *::before, *::after {
box-sizing: border-box;
}

选择器优先级

优先级由选择器的”特异性”决定,从低到高:标签选择器 < 类选择器 < ID 选择器 < 行内样式 < !important

实践中要警惕的是一种情况:你的样式不生效,检查半天发现是被一个更具体的祖先选择器覆盖了。打开浏览器 DevTools 的 Styles 面板,被覆盖的规则会有删除线,直接就能看到谁在打架。

布局:从 Flexbox 开始

传统的 float + position 布局能实现大多数效果,但心智负担大——清除浮动、垂直居中、等高列,每个都是坑。

Flexbox 解决了一维布局(单行/单列)的问题。容器设置 display: flex,用 justify-content 控制主轴对齐、align-items 控制交叉轴对齐。过去需要各种 hack 的垂直居中,现在就是两行属性的事。

Grid 解决二维布局(行列网格)。适合页面整体结构、卡片排列等场景。一般建议”外层 Grid、内层 Flexbox”的组合——Grid 定大框架,Flexbox 处理组件内部的排列。

定位机制

position 的四种值不是四个孤立的选项,它们决定的是元素的”定位参考系”:

  • static:默认,跟随文档流
  • relative:相对于自己原本的位置偏移,但原位置仍然被占用
  • absolute:相对于最近的 positionstatic 的祖先元素定位,脱离文档流
  • fixed:相对于浏览器视口定位,脱离文档流,滚动不影响位置

一个常见场景:父元素设 position: relative,子元素设 position: absolute,然后用 top/left/right/bottom 精确控制子元素在父元素内的位置。

JavaScript:让页面可交互

JavaScript 的学习曲线比 HTML 和 CSS 加起来都陡。核心在于它不是一套属性可以死记硬背的——它需要你理解程序的运行逻辑。

变量与作用域

var 是函数作用域,letconst 是块级作用域。现代代码里不要再用 var,用 const 作为默认声明方式,只在确实需要重新赋值时用 let

值类型 vs 引用类型

基本类型(number、string、boolean 等)赋值时复制值;对象和数组赋值时复制引用。

1
2
3
4
let a = { name: 'A' };
let b = a;
b.name = 'B';
console.log(a.name); // 'B'——a 和 b 指向同一个对象

做深拷贝时,JSON.parse(JSON.stringify(obj)) 能覆盖简单场景,但处理不了 DateFunction、循环引用。生产代码用 structuredClone() 或 lodash 的 cloneDeep

异步与事件循环

这是 JavaScript 最核心也最容易被误解的机制。执行顺序是:同步代码 → 微任务(Promise.then)→ 宏任务(setTimeout、事件回调)。

1
2
3
4
5
console.log('1');           // 同步,先输出
setTimeout(() => console.log('2'), 0); // 宏任务,最后输出
Promise.resolve().then(() => console.log('3')); // 微任务,其次输出
console.log('4'); // 同步,紧接着输出
// 输出顺序: 1, 4, 3, 2

理解这个顺序对调试异步代码至关重要。

DOM 操作

原生 DOM API 写起来啰嗦,但在用 Vue/React 之前,你应该知道浏览器原生是怎么做的:

1
2
3
4
const div = document.createElement('div');
div.textContent = 'Hello';
div.classList.add('box');
document.body.appendChild(div);

以及事件代理——把事件监听绑在父元素上,通过 event.target 判断实际点击的是哪个子元素。这是处理动态列表点击事件的标准做法,能避免给每个子元素单独绑定事件。

Vue:数据驱动视图

核心理念

传统方式是用 JS 找到 DOM 节点然后修改它的内容。Vue 把这个过程反过来:你修改数据,Vue 负责更新 DOM。这不仅是代码量的减少,更是一种思维模型的改变——你不再关心”怎么改 DOM”,只关心”数据是什么”。

指令

v-ifv-show 都控制显示隐藏,但机制不同:

  • v-if:条件为假时元素不渲染,切换开销大
  • v-show:始终渲染,只是切换 display 属性,切换开销小

结论:频繁切换的场景用 v-show,条件很少变化的用 v-if

v-for 遍历数据生成列表。:key 属性不是可选的——它是 Vue 的虚拟 DOM diff 算法用来追踪每个节点的标识。没有 key 或 key 用 index,在列表增删时可能出现渲染错位。

组件通信

组件通信有三种模式,按适用范围从小到大排列:

父传子——Props:父组件通过属性把数据传给子组件。数据流是单向的,子组件不应该修改 props。

子传父——事件:子组件用 $emit 触发事件,父组件监听事件并响应。本质上是在子组件里通知父组件”有事情发生了,你来处理”。

跨层级——状态管理:两个不相关的组件需要共享数据时,小项目用 EventBus 模式(emit/on),大项目用 Pinia(Vue 3 官方推荐,替代了 Vuex)。不要在还没遇到痛点时就上状态管理库——你迟早会遇到,到那时候你才知道你真正需要什么。

常见决策

计算属性 vs 方法:计算属性有缓存,依赖不变就不会重新计算。如果一个值被多次用到且依赖固定数据,用 computed 而不是 method。

组件拆分粒度:一个组件超过 200 行就应该考虑拆分。但不要为了拆分而拆分——如果两段逻辑紧密耦合、传参超过 4 个、拆开后理解成本更高,那就留在一起。

局部状态 vs 全局状态:优先局部。只有确实需要跨多个不相关组件共享的状态才放进全局 store。把”当前表单的输入值”放进 Vuex/Pinia 是过度设计。

学习路径

按时间线排下来大致是这样。每个人的基础和节奏不同,但顺序基本固定:

  1. HTML + CSS(2-3 周):目标是能独立把一个设计稿还原成静态页面。过程中你会大量接触盒模型和 Flexbox,这是后面一切的基础。
  2. JavaScript(3-4 周):重点在异步、作用域、原型链、DOM 操作。建议同时做小的交互练习——表单验证、轮播图、TODO 列表——而不是只看不写。
  3. Vue(2-3 周):用 Vue 重写之前纯 JS 写的 TODO 列表和表单,你能直观感受到”数据驱动”和”手动操作 DOM”的区别。
  4. 综合项目(持续):个人博客、后台管理系统都可以。这个阶段练的不是语法,是工程意识——文件怎么组织、组件怎么拆、状态放哪里、接口怎么处理。