前端三剑客 + Vue:从零到一的知识体系
HTML、CSS、JavaScript 与 Vue:从零到一的知识结构
前端的学习路径有一个独特的问题:每个知识点单独学都不难,但把它们组装成一个能跑的应用时,脑子里的知识是散的。这篇文章的目的是帮你建立一套从 HTML 到 Vue 的连贯认知,知道每个技术在前端体系里的位置,以及工作中真正用到的是什么。
HTML:内容的骨架
HTML 不是编程语言。它是一个声明式的文档格式——告诉浏览器”这里有个标题”、”这里是个按钮”,浏览器负责把它们画出来。
你真正需要掌握的就三件事:
文档流。块级元素(div、section、p)独占一行;行内元素(span、a)跟在同一行。理解这个区别是理解一切 CSS 布局的前提。之后学 Flexbox 和 Grid,本质上是在改变默认的文档流行为。
语义化。用 <header>、<nav>、<main>、<article> 而不是一律 <div class="xxx">。不只是为了 SEO,更实际的好处是你的代码结构一眼就能看懂。
表单。<form>、<input>、<select>、<button> 这些是工作中打交道最多的标签。原生的表单验证(required、pattern、type="email")能省不少 JS 代码。
HTML 本身不会是你学习的瓶颈。花一个下午过一遍 MDN 的 HTML 元素参考,知道有哪些标签就够了。真正花时间的在 CSS。
CSS:布局和样式的现实
盒模型
浏览器把每个元素看作一个矩形盒子,由内到外依次是 content、padding、border、margin。
标准盒模型中,width 只作用于 content 区域。设置 width: 200px; padding: 20px; 之后,元素实际占用的水平空间是 242px(200 + 40 内边距 + 2 边框)。
box-sizing: border-box 把 width 的含义改成”从 border 到 border”,包含 content、padding 和 border。这是目前几乎所有项目都会在全局样式中设置的属性:
1 | *, *::before, *::after { |
选择器优先级
优先级由选择器的”特异性”决定,从低到高:标签选择器 < 类选择器 < ID 选择器 < 行内样式 < !important。
实践中要警惕的是一种情况:你的样式不生效,检查半天发现是被一个更具体的祖先选择器覆盖了。打开浏览器 DevTools 的 Styles 面板,被覆盖的规则会有删除线,直接就能看到谁在打架。
布局:从 Flexbox 开始
传统的 float + position 布局能实现大多数效果,但心智负担大——清除浮动、垂直居中、等高列,每个都是坑。
Flexbox 解决了一维布局(单行/单列)的问题。容器设置 display: flex,用 justify-content 控制主轴对齐、align-items 控制交叉轴对齐。过去需要各种 hack 的垂直居中,现在就是两行属性的事。
Grid 解决二维布局(行列网格)。适合页面整体结构、卡片排列等场景。一般建议”外层 Grid、内层 Flexbox”的组合——Grid 定大框架,Flexbox 处理组件内部的排列。
定位机制
position 的四种值不是四个孤立的选项,它们决定的是元素的”定位参考系”:
static:默认,跟随文档流relative:相对于自己原本的位置偏移,但原位置仍然被占用absolute:相对于最近的position非static的祖先元素定位,脱离文档流fixed:相对于浏览器视口定位,脱离文档流,滚动不影响位置
一个常见场景:父元素设 position: relative,子元素设 position: absolute,然后用 top/left/right/bottom 精确控制子元素在父元素内的位置。
JavaScript:让页面可交互
JavaScript 的学习曲线比 HTML 和 CSS 加起来都陡。核心在于它不是一套属性可以死记硬背的——它需要你理解程序的运行逻辑。
变量与作用域
var 是函数作用域,let 和 const 是块级作用域。现代代码里不要再用 var,用 const 作为默认声明方式,只在确实需要重新赋值时用 let。
值类型 vs 引用类型
基本类型(number、string、boolean 等)赋值时复制值;对象和数组赋值时复制引用。
1 | let a = { name: 'A' }; |
做深拷贝时,JSON.parse(JSON.stringify(obj)) 能覆盖简单场景,但处理不了 Date、Function、循环引用。生产代码用 structuredClone() 或 lodash 的 cloneDeep。
异步与事件循环
这是 JavaScript 最核心也最容易被误解的机制。执行顺序是:同步代码 → 微任务(Promise.then)→ 宏任务(setTimeout、事件回调)。
1 | console.log('1'); // 同步,先输出 |
理解这个顺序对调试异步代码至关重要。
DOM 操作
原生 DOM API 写起来啰嗦,但在用 Vue/React 之前,你应该知道浏览器原生是怎么做的:
1 | const div = document.createElement('div'); |
以及事件代理——把事件监听绑在父元素上,通过 event.target 判断实际点击的是哪个子元素。这是处理动态列表点击事件的标准做法,能避免给每个子元素单独绑定事件。
Vue:数据驱动视图
核心理念
传统方式是用 JS 找到 DOM 节点然后修改它的内容。Vue 把这个过程反过来:你修改数据,Vue 负责更新 DOM。这不仅是代码量的减少,更是一种思维模型的改变——你不再关心”怎么改 DOM”,只关心”数据是什么”。
指令
v-if 和 v-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 是过度设计。
学习路径
按时间线排下来大致是这样。每个人的基础和节奏不同,但顺序基本固定:
- HTML + CSS(2-3 周):目标是能独立把一个设计稿还原成静态页面。过程中你会大量接触盒模型和 Flexbox,这是后面一切的基础。
- JavaScript(3-4 周):重点在异步、作用域、原型链、DOM 操作。建议同时做小的交互练习——表单验证、轮播图、TODO 列表——而不是只看不写。
- Vue(2-3 周):用 Vue 重写之前纯 JS 写的 TODO 列表和表单,你能直观感受到”数据驱动”和”手动操作 DOM”的区别。
- 综合项目(持续):个人博客、后台管理系统都可以。这个阶段练的不是语法,是工程意识——文件怎么组织、组件怎么拆、状态放哪里、接口怎么处理。
