学习地图
这门学科是干什么的
Vue 是一个用于构建用户界面的前端框架。它最核心的事情只有一句话:让页面随着数据变化而自动更新 。
你真正要学的,不只是几个 API,而是三件事:
- 用"组件"拆页面。
- 用"状态"驱动界面。
- 用"工程化方式"组织前端项目。
学习本质:必须吃透
Vue 本质上是在帮我们把"业务状态"和"页面表现"建立稳定映射。
一句最重要的话可以记住:UI = f(state),界面是状态的函数。
它解决什么问题
在没有框架时,前端经常要手动操作 DOM:
- 找元素
- 改文本
- 改 class
- 绑定事件
- 手动同步数据和界面
页面一复杂,就会出现三个典型问题:
| 问题 | 原生方式常见表现 | Vue 的解决方式 |
|---|---|---|
| 界面和数据容易不同步 | 数据改了,但 DOM 忘了改 | 响应式系统自动追踪依赖并更新视图 |
| 页面难复用 | 一页一套 DOM + JS | 用组件封装和复用 |
| 项目一大就混乱 | JS、HTML、状态、接口逻辑耦合 | 用组件、路由、状态管理拆分职责 |
它和哪些相关技术有关系
| 相关技术 | 和 Vue 的关系 | 是否前置必备 |
|---|---|---|
| HTML/CSS | Vue 模板最终还是渲染成 HTML,样式仍然靠 CSS | 是 |
| JavaScript | Vue 的本体就是基于 JS 的 | 是 |
| ES6+ | 模块化、解构、箭头函数、Promise 很常用 | 是 |
| DOM / 浏览器事件 | 帮助理解 Vue 为什么能接管页面更新 | 是 |
| Node.js / npm | 创建项目、安装依赖、运行开发服务 | 是 |
| Vite | 现在最常见的 Vue 构建工具 | 是 |
| Vue Router | 做多页面感受的单页应用导航 | 很重要 |
| Pinia | 管理跨组件共享状态 | 很重要 |
| Axios / Fetch | 请求后端接口 | 很重要 |
| TypeScript | 企业项目里很常见,但不是一上来必须精通 | 先知道,后深入 |
| SSR / Nuxt | 服务端渲染与全栈能力 | 先知道,后深入 |
学它之前需要哪些前置知识
建议至少具备下面这些基础,不需要很深,但要会用:
- HTML 基础:标签、表单、列表、语义化。
- CSS 基础:选择器、盒模型、Flex、定位。
- JavaScript 基础:变量、函数、对象、数组、作用域。
- ES6 常用语法:模块化、解构、模板字符串、Promise、async/await。
- 浏览器基础:DOM、事件冒泡、默认行为、网络请求。
- 命令行基础:
cd、npm install、npm run dev。
如果你现在 JS 还不熟,学习顺序一定是:先补 JS 常用语法,再学 Vue 。
因为 Vue 的难点,很多时候并不是框架本身,而是 JS、组件思维和异步思维。
真正重要的 20% 核心内容是什么
下面这些内容,占了 Vue 实战和面试里最有价值的 80%:
- 组件化思维:怎么拆页面、怎么复用组件。
- 模板语法与指令 :插值、
v-bind、v-model、v-if、v-for、事件绑定。 - 响应式数据 :
ref、reactive、数据变化为什么会驱动视图更新。 - 组件通信 :
props、emit、provide / inject、状态管理的适用边界。 - 计算属性与侦听器 :
computed、watch、watchEffect的区别和场景。 - 生命周期:什么时候发请求、什么时候操作 DOM、什么时候清理副作用。
- 路由与页面组织:Vue Router 的路由匹配、导航、嵌套路由、守卫。
- 状态管理:Pinia 如何管理全局状态。
- 接口请求与异步状态处理:加载中、错误态、空态、重试。
- 基础排错能力 :组件不更新、
key用错、响应式丢失、props误改、nextTick误用。
哪些内容是初学者容易陷入、但不值得一开始深挖的
这些内容不是不重要,而是不该在最开始投入过多时间:
- Vue 源码逐行阅读。
- 编译器细节,比如模板 AST 的每个转换过程。
- 自定义渲染器。
- SSR / Nuxt 的复杂部署。
- 极限性能优化和复杂构建链魔改。
- 太早陷入"Vue 2 和 Vue 3 所有差异背诵"。
- 太早陷入"所有生态库全都学一遍"。
建议原则:
- 必须掌握:组件、响应式、通信、生命周期、路由、状态管理、排错。
- 知道即可:SSR、宏观源码架构、编译器实现细节、高阶性能调优。
设计哲学
Vue 的设计哲学可以概括成三句话:
- 渐进式:你可以从一页小功能开始用,也可以做完整工程项目。
- 声明式:你描述"页面应该长什么样",不是手写每一次 DOM 修改过程。
- 组合式:逻辑按能力组织,而不是按生命周期函数强行分散。
学习顺序
下面是推荐的学习顺序,也是企业里最接近真实成长路径的一条线:
-
第一阶段:入门认知
理解 Vue 在前端中的角色,能跑起第一个应用,知道"为什么页面会自动更新"。
-
第二阶段:核心语法与组件
掌握模板语法、指令、组件、
props、事件、表单、列表、条件渲染。 -
第三阶段:响应式与组件通信机制
吃透
ref、reactive、computed、watch、生命周期,以及父子、兄弟、跨层通信。 -
第四阶段:底层原理
理解响应式追踪、依赖收集、调度更新、虚拟 DOM、Diff、
nextTick、模板编译链路。 -
第五阶段:工程实践
会用 Vite、Vue Router、Pinia、接口封装、目录结构、组件规范、环境配置、构建发布。
-
第六阶段:常见问题与排错
能定位"不更新""重复渲染""路由失效""状态丢失""样式污染""异步竞态"等问题。
-
第七阶段:面试与评估
把知识整理成可以解释、可以对比、可以落到代码和场景的答案。
-
第八阶段:项目闭环
完成一个中小型项目,把知识点串起来,形成"会做 + 会讲 + 会排错"的能力。
正确学习顺序为什么是这样
因为 Vue 学偏最常见的原因有两个:
- 一开始背 API,不理解"状态驱动视图"。
- 一开始啃源码,却没有真实业务问题作为抓手。
所以正确路径一定是:
先直觉认知 -> 再掌握常用 API -> 再理解机制 -> 再进入工程与源码。
企业里通常怎么用 Vue
企业里最常见的组合是:
Vue 3 + ViteVue RouterPiniaAxios / FetchElement Plus / Ant Design Vue / 自研组件库TypeScript(很多团队会加)
面试官通常怎么问
初级到中级 Vue 面试,常见问法通常分四类:
- 概念类:Vue 是什么?响应式是什么?
computed和watch区别是什么? - 机制类:Vue 为什么更新快?
nextTick是干什么的?key为什么重要? - 工程类:项目怎么拆组件?如何管理公共状态?接口如何封装?
- 排错类:为什么页面不更新?为什么列表复用有问题?为什么子组件不能直接改
props?
自循环推进规则
从这里开始,这份文档不再依赖"回复继续"才能往下学,而是按下面的闭环自动推进:
- 先学当前阶段的主干内容。
- 跑通当前阶段的最小示例。
- 完成当前阶段的练习题或工程任务。
- 对照当前阶段的"学完标志"和"验收标准"自测。
- 如果自测正确率在 80% 以上,直接进入下一阶段。
- 如果自测正确率低于 80%,先按文末"反向补课"回补,再继续推进。
建议学习节奏:
- 第一到第三阶段:重在建立正确直觉和常用写法。
- 第四到第六阶段:重在理解为什么这样设计,以及怎么排错。
- 第七到第八阶段:重在把知识变成面试表达和项目能力。
你可以把这份文档当成一个可循环执行的学习流程:
学概念 -> 写示例 -> 做练习 -> 自测 -> 查漏补缺 -> 进入下一阶段 -> 项目闭环
第一阶段:Vue 到底是什么,为什么它能让页面跟着数据走
1. 学什么
这一阶段你要建立三个最重要的直觉:
- Vue 不是"一个会写页面的语法糖",而是一个状态驱动 UI 的框架。
- Vue 的基本单位是组件,不是一整页代码。
- Vue 的核心价值是:你改数据,Vue 帮你更新页面。
本阶段只要求你掌握下面这些最基础但最关键的内容:
- Vue 在前端中的角色
- 声明式开发是什么
- 组件是什么
- 响应式更新是什么
createApp、setup、ref的最基本使用- Vue 项目如何跑起来
2. 为什么重要
如果这一阶段没吃透,后面所有内容都会变成"背 API":
- 你会记住
v-model,但不知道它为什么存在。 - 你会记住
watch,但不知道什么时候该用。 - 你会记住生命周期,但不知道为什么有这些时机。
所以这一阶段最重要的目标不是"写复杂页面",而是建立一个稳定认知:
Vue 通过响应式系统,把数据变化映射为视图变化。
3. 核心概念
3.1 先用直觉理解
可以把 Vue 想成一个"聪明的前台屏幕系统":
- 你手里改的是后台数据。
- 屏幕上展示的是这些数据的结果。
- 只要数据变了,屏幕自动刷新,不需要你再一个个找 DOM 改。
3.2 技术定义
| 概念 | 直觉类比 | 技术定义 |
|---|---|---|
| 声明式 UI | 告诉厨师"我要什么菜",而不是自己切菜下锅 | 描述数据和视图关系,而不是手动操作 DOM 过程 |
| 组件 | 乐高积木 | 可复用、可组合的 UI 与逻辑单元 |
| 响应式 | 温度计会跟温度自动变化 | 数据变化后,依赖它的视图或逻辑会自动重新执行 |
| 模板 | 页面草图 | 用接近 HTML 的语法描述视图结构 |
| 状态 | 当前系统的事实 | 决定页面展示结果的数据 |
| 挂载 | 把程序接到页面上 | Vue 应用接管某个 DOM 容器并开始渲染 |
3.3 必须吃透
下面这句话请你反复看:
以前是"我去改页面",现在是"我改状态,框架改页面"。
这是 Vue 和原生 DOM 编程最大的分界线。
4. 原理解释
4.1 Vue 的工作流程
当你写出一个 Vue 页面时,大致发生了下面这些事情:
createApp()创建一个应用实例。mount('#app')把应用挂到页面上的某个容器。- Vue 读取模板,建立"模板依赖了哪些数据"的关系。
- 你在
setup()里定义响应式数据,比如ref(0)。 - 模板使用了这个数据,比如
{``{ count }}。 - 当
count变化时,Vue 知道这个值被页面依赖了。 - Vue 不会粗暴整页重画,而是找到需要更新的部分,补丁式更新 DOM。
4.2 为什么这样设计
Vue 这样设计,是为了同时解决三个问题:
- 开发效率:不再每次都手动改 DOM。
- 可维护性:页面逻辑以组件和状态组织,更清晰。
- 性能平衡:通过依赖追踪和批量调度,避免无意义重渲染。
4.3 一个必须知道的底层思想
虽然你现在不用深入源码,但要先知道下面这条主线:
响应式数据 -> 依赖收集 -> 数据变化 -> 调度更新 -> DOM 打补丁
后面学 computed、watch、nextTick、虚拟 DOM 时,都会回到这条链路。
5. 示例
5.1 最小可运行示例
下面这个例子可以直接保存为 index.html 后打开运行:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue 最小示例</title>
</head>
<body>
<div id="app">
<h1>当前计数:{{ count }}</h1>
<button @click="count++">加 1</button>
<button @click="reset">重置</button>
<p v-if="count >= 3">你已经点击了至少 3 次</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const count = ref(0)
const reset = () => {
count.value = 0
}
return {
count,
reset
}
}
}).mount('#app')
</script>
</body>
</html>
5.2 这个示例说明了什么
这个例子虽然小,但已经覆盖了 Vue 的基础骨架:
createApp:创建应用setup:编写组件逻辑ref:创建响应式数据{``{ count }}:模板插值@click:事件绑定v-if:条件渲染
5.3 为什么模板里不需要写 .value
在 JavaScript 里,ref 的值需要通过 count.value 访问。
但在模板里,Vue 会帮你自动解包,所以直接写 count。
6. 工程实践
6.1 标准起步方式
真实项目里,一般不会直接用 CDN 起步,而是用 Vite 创建 Vue 工程:
bash
npm create vue@latest
cd your-project
npm install
npm run dev
6.2 你会看到的核心目录
text
your-project/
├─ public/
├─ src/
│ ├─ assets/
│ ├─ components/
│ ├─ App.vue
│ └─ main.js
├─ index.html
├─ package.json
└─ vite.config.js
6.3 一个真实工程场景
假设你要做一个"学生管理页面",页面上有:
- 学生列表
- 搜索框
- 新增按钮
- 删除按钮
- 详情弹窗
而 Vue 的做法会是:
- 把页面拆成列表组件、搜索组件、弹窗组件。
- 把"学生数据"和"当前筛选条件"作为状态。
- 模板根据状态自动渲染结果。
- 用户点击按钮,实际改的是状态,不是手动改一堆 DOM。
7. 常见误区
- 把 Vue 当成模板拼接工具
- 上来就背很多 API
- 在 Vue 里还习惯手动操作 DOM
- 分不清
ref和普通变量 - 一开始就沉迷源码
- 学 Vue 却不补 JavaScript
8. 面试题
- Vue 是什么?它解决了什么问题?
- 什么是声明式开发?
- Vue 为什么能在数据变化时自动更新页面?
ref是什么?为什么模板里不用写.value?createApp().mount()做了什么?
9. 自测题
- 用你自己的话解释:为什么说 Vue 是"状态驱动 UI"的框架?
- 原生 DOM 手动更新页面,和 Vue 响应式更新页面,本质差别是什么?
ref(0)和let count = 0在 Vue 组件里有什么本质区别?createApp、setup、mount分别负责什么?- 为什么说组件是 Vue 项目的基本组织单位?
- 如果点击按钮后数据变了,但页面没变,你第一反应应该检查什么?
10. 学完标志
学完这一阶段后,你应该能做到:
- 用自己的话解释 Vue 是什么,以及它为什么比手动 DOM 操作更适合复杂页面。
- 说清楚"声明式开发""组件""响应式"的含义。
- 独立跑起一个 Vue 项目。
- 写出一个最小可运行组件,包含数据、事件和条件渲染。
- 初步解释"为什么数据变了,页面会跟着变"。
第一阶段练习题
练习 1:计数器增强版
要求你实现:
- 一个数字计数器。
- 一个"加 1"按钮。
- 一个"减 1"按钮。
- 一个"重置"按钮。
- 当数字大于等于 5 时显示提示文字。
- 当数字小于 0 时,文字变成红色。
练习 2:个人信息卡片
要求你实现:
- 页面展示姓名、年龄、职业。
- 点击按钮后年龄加 1。
- 点击按钮切换"在职 / 离职"状态。
- 用条件渲染显示不同文案。
练习 3:待办事项最小版
要求你实现:
- 输入框输入待办内容。
- 点击按钮新增一条待办。
- 页面显示待办列表。
- 每条待办旁边有删除按钮。
第一阶段验收标准
如果你能独立完成上面 3 个练习中的至少 2 个,并且能口头回答下面这 4 个问题,就算第一阶段基本达标:
- Vue 为什么适合做复杂前端页面?
- 什么是响应式数据?
- 为什么我们更推荐"改状态"而不是"手动改 DOM"?
- 一个 Vue 项目最基本是怎么启动起来的?
第二阶段:模板语法、组件拆分与页面表达
1. 学什么
这一阶段开始真正进入"会写页面"的部分,重点掌握:
- 插值表达式
{``{ }} - 属性绑定
v-bind - 事件绑定
v-on - 表单双向绑定
v-model - 条件渲染
v-if、v-else-if、v-else、v-show - 列表渲染
v-for - 列表更新中的
key - 单文件组件
*.vue - 基础组件拆分
props和emit的基础使用
2. 为什么重要
这一阶段是 Vue 日常开发里使用频率最高的一层。
如果说第一阶段是在建立"状态驱动视图"的认知,那么第二阶段就是把这个认知翻译成具体代码。
企业开发中,你每天都在写这层内容:
- 表单输入
- 条件展示
- 列表渲染
- 点击事件
- 组件传值
- 页面拆分
3. 核心概念
3.1 指令是什么
Vue 指令就是带 v- 前缀的特殊语法,用来描述"数据怎么影响页面"。
| 指令 | 作用 | 高频场景 |
|---|---|---|
v-bind |
动态绑定属性 | src、class、disabled |
v-on / @ |
绑定事件 | 点击、输入、提交 |
v-model |
双向绑定表单值 | 输入框、下拉框、单选框 |
v-if |
条件创建 / 销毁节点 | 弹窗、权限区块 |
v-show |
条件切换显示隐藏 | 高频切换的面板 |
v-for |
列表渲染 | 列表、表格、菜单 |
3.2 v-if 和 v-show 对比
| 项目 | v-if |
v-show |
|---|---|---|
| 本质 | 控制节点是否创建 | 控制 CSS display |
| 初始成本 | 条件为假时不渲染 | 一开始就渲染 |
| 切换成本 | 每次切换可能销毁和重建 | 切换很快 |
| 适用场景 | 不常切换、结构较重 | 高频切换、结构较轻 |
3.3 props 和 emit 对比
| 概念 | 方向 | 作用 |
|---|---|---|
props |
父 -> 子 | 父组件给子组件传数据 |
emit |
子 -> 父 | 子组件通知父组件发生了某个事件 |
4. 原理解释
4.1 模板为什么能写得像 HTML
因为 Vue 会把模板编译成渲染函数。
你看到的是接近 HTML 的声明式写法,Vue 内部执行的是 JavaScript 渲染逻辑。
4.2 v-model 为什么是语法糖
它本质上是两件事的组合:
- 把值绑定到表单元素上。
- 在输入变化时同步回数据。
你可以把它理解成:
vue
<input :value="keyword" @input="keyword = $event.target.value" />
4.3 为什么 v-for 一定要重视 key
因为 key 就是列表项的"身份证"。
如果 key 写错,比如直接写索引:
- 删除一项时可能复用错 DOM
- 输入框值可能串位
- 局部状态可能错乱
5. 示例
5.1 最小可运行示例
App.vue
vue
<template>
<div>
<h2>待办列表</h2>
<input v-model="keyword" placeholder="请输入关键词" />
<button @click="addTodo">新增</button>
<p v-if="filteredTodos.length === 0">暂无数据</p>
<TodoList :items="filteredTodos" @remove="removeTodo" />
</div>
</template>
<script setup>
import { computed, ref } from 'vue'
import TodoList from './components/TodoList.vue'
const keyword = ref('')
const todos = ref([
{ id: 1, text: '学习 Vue' },
{ id: 2, text: '写一个待办应用' }
])
const filteredTodos = computed(() =>
todos.value.filter(item => item.text.includes(keyword.value))
)
const addTodo = () => {
if (!keyword.value.trim()) return
todos.value.push({
id: Date.now(),
text: keyword.value
})
keyword.value = ''
}
const removeTodo = (id) => {
todos.value = todos.value.filter(item => item.id !== id)
}
</script>
components/TodoList.vue
vue
<template>
<ul>
<li v-for="item in items" :key="item.id">
<span>{{ item.text }}</span>
<button @click="$emit('remove', item.id)">删除</button>
</li>
</ul>
</template>
<script setup>
defineProps({
items: {
type: Array,
default: () => []
}
})
defineEmits(['remove'])
</script>
6. 工程实践
6.1 实际开发操作步骤
- 先画出页面结构。
- 判断哪些是静态部分,哪些是动态部分。
- 找出页面状态:输入值、列表数据、当前选中项、显示隐藏状态。
- 决定哪些内容放父组件,哪些拆成子组件。
- 用
props传数据,用emit回传事件。 - 给列表项补稳定
key。 - 最后再考虑样式和细节交互。
6.2 一个真实工程场景
比如做"商品列表页":
- 父组件负责:关键词、筛选项、商品数组、请求状态。
- 搜索栏组件负责:输入和点击搜索。
- 商品卡片组件负责:展示单个商品信息。
- 分页组件负责:页码切换。
7. 常见误区
- 把所有东西都写在一个组件里
- 子组件直接修改
props v-for用索引当key- 把
v-if和v-for写在同一个节点上 - 认为
v-model是"Vue 黑魔法"
8. 面试题
v-if和v-show有什么区别?分别适合什么场景?v-model的本质是什么?- 为什么
v-for需要key?如果不用会怎样? - 父子组件怎么通信?
- 为什么子组件不能直接修改
props?
9. 自测题
- 你能不用看资料写出
v-bind、v-model、v-for的基本用法吗? - 你能说清楚
v-if和v-show的性能差异吗? - 你能独立把一个页面拆成父组件和两个子组件吗?
- 你能解释为什么
key应该用稳定唯一值吗? - 如果子组件点击删除按钮,你知道为什么更推荐用
emit通知父组件,而不是子组件直接删数据吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 用 Vue 写出表单、列表、条件显示页面。
- 独立完成基础组件拆分。
- 正确使用
props和emit完成父子通信。 - 说清楚
v-if、v-show、v-model、v-for、key的场景和原理直觉。
第三阶段:响应式、生命周期与组件通信机制
1. 学什么
这一阶段进入 Vue 的核心能力层,重点是:
ref和reactivecomputedwatch和watchEffect- 生命周期钩子
- 父子、兄弟、跨层组件通信
provide / inject- 共享状态该什么时候上 Pinia,什么时候不需要
2. 为什么重要
Vue 真正的"框架味道",主要就在这一层。
初学者最容易卡住的地方,不是模板,而是下面这些问题:
- 为什么有时候数据变了页面不变?
computed和watch到底该用哪个?- 接口请求该放在哪个生命周期里?
- 父组件、子组件、跨层组件之间如何传值才不乱?
3. 核心概念
3.1 ref 和 reactive
| 概念 | 适合什么数据 | 访问方式 | 常见场景 |
|---|---|---|---|
ref |
基本类型,也可包对象 | JS 中用 .value |
数字、字符串、布尔值、DOM 引用 |
reactive |
对象、数组 | 直接访问属性 | 表单对象、复杂状态对象 |
3.2 computed、watch、watchEffect
| 概念 | 作用 | 适合场景 |
|---|---|---|
computed |
计算派生值,有缓存 | 筛选结果、格式化显示、统计值 |
watch |
监听指定源变化并执行副作用 | 发请求、同步本地存储、路由联动 |
watchEffect |
自动收集内部依赖并执行 | 快速编写依赖驱动副作用 |
一句话区分:
- 派生新值,用
computed - 响应变化做副作用,用
watch
3.3 生命周期
| 钩子 | 常见用途 |
|---|---|
onMounted |
获取初始数据、访问真实 DOM |
onUpdated |
某次更新后观察 DOM 结果 |
onUnmounted |
清理定时器、事件监听、订阅 |
3.4 组件通信怎么选
| 场景 | 推荐方式 |
|---|---|
| 父 -> 子 | props |
| 子 -> 父 | emit |
| 跨层但层级固定 | provide / inject |
| 多组件共享、页面级甚至全局状态 | Pinia |
4. 原理解释
4.1 computed 为什么比函数更适合派生值
因为它有缓存。
只要依赖没变,computed 不会重复计算。
4.2 watch 为什么容易被滥用
因为很多人把"派生值"也写成 watch。
结果是本来可以通过公式推导的关系,被写成了同步脚本。
4.3 生命周期为什么存在
因为组件不是永远静止的,它有自己的运行过程:
- 创建
- 渲染
- 挂载到 DOM
- 更新
- 卸载
5. 示例
5.1 最小可运行示例
vue
<template>
<div>
<h2>商品搜索</h2>
<input v-model="keyword" placeholder="输入关键词" />
<p>命中数量:{{ matchedCount }}</p>
<ul>
<li v-for="item in filteredProducts" :key="item.id">
{{ item.name }} - {{ item.price }} 元
</li>
</ul>
</div>
</template>
<script setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
const keyword = ref('')
const state = reactive({
products: []
})
onMounted(() => {
state.products = [
{ id: 1, name: 'Vue 实战课程', price: 99 },
{ id: 2, name: 'JavaScript 手册', price: 59 },
{ id: 3, name: 'Vue Router 指南', price: 39 }
]
})
const filteredProducts = computed(() =>
state.products.filter(item => item.name.includes(keyword.value))
)
const matchedCount = computed(() => filteredProducts.value.length)
watch(keyword, (newValue) => {
localStorage.setItem('last-keyword', newValue)
})
</script>
6. 工程实践
6.1 实战中的选择原则
- 页面展示用到的原始值,放
ref或reactive。 - 所有"由已有值推出来的新值",优先考虑
computed。 - 所有"监听变化后要去做外部动作"的逻辑,才考虑
watch。 - 接口首屏加载常放在
onMounted。 - 定时器、订阅、全局事件监听,在
onUnmounted里清理。
6.2 一个真实工程场景
做"订单列表页"时常见状态有:
- 查询条件
- 当前页码
- 订单列表
- 加载中状态
- 总数
7. 常见误区
- 用
watch代替computed - 所有对象都用
reactive,所有值都混着写 - 忘记清理副作用
- 任何共享数据都塞进全局 store
- 误以为
watchEffect是更高级的watch
8. 面试题
ref和reactive有什么区别?computed和watch的区别是什么?- 什么时候用
watchEffect? - Vue 生命周期最常用的是哪些?分别适合做什么?
- 如果多个组件都依赖同一份状态,你会怎么设计?
9. 自测题
- 你能举出三个必须用
computed而不该用watch的场景吗? - 你能解释为什么"搜索结果数量"适合
computed吗? - 你能说出
onMounted和onUnmounted各自处理哪类逻辑吗? - 你能给一个"局部状态不该放 Pinia"的例子吗?
- 你能不用资料写出一个
watch监听输入框并同步本地存储的例子吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 正确区分原始状态、派生状态、副作用。
- 正确使用
ref、reactive、computed、watch。 - 知道请求、DOM 操作、清理逻辑该放在哪个生命周期。
- 能为父子通信、跨层通信、共享状态选择合理方案。
第四阶段:底层原理,理解 Vue 为什么这样设计
1. 学什么
这一阶段是从"会用"走向"能解释"的关键层,重点包括:
- 响应式原理:
Proxy、依赖收集、触发更新 effect、track、trigger- 调度更新与批量刷新
nextTick- 虚拟 DOM
- Diff 与
key - 模板编译流程
- 为什么 Vue 3 比 Vue 2 在响应式层更现代
2. 为什么重要
中级工程师和只会写页面的区别,很大一部分就在这里:
- 你能不能解释"为什么
key重要" - 你能不能解释"为什么 DOM 更新不是同步立刻发生"
- 你能不能解释"为什么
computed有缓存" - 你能不能解释"为什么模板能转换成渲染函数"
3. 核心概念
3.1 响应式主链路
读取响应式数据 -> 收集依赖 -> 数据变化 -> 触发副作用 -> 调度更新 -> Patch DOM
3.2 关键术语
| 术语 | 含义 |
|---|---|
Proxy |
对对象访问进行拦截,Vue 3 用它做响应式代理 |
track |
在读取数据时记录"谁依赖了我" |
trigger |
在修改数据时通知依赖重新执行 |
effect |
依赖响应式数据的执行函数 |
| Scheduler | 控制更新时机,做批量合并 |
| Virtual DOM | 用 JS 对象描述 UI 结构 |
| Patch | 比较新旧节点后,最小化更新真实 DOM |
3.3 Vue 运行流程图
响应式数据被读取
track: 收集依赖
数据发生变化
trigger: 通知依赖
调度器合并更新
重新生成虚拟 DOM
Diff 比较新旧节点
Patch 到真实 DOM
4. 原理解释
4.1 为什么 Vue 3 用 Proxy
因为 Proxy 可以拦截对象的更多操作,能力更完整。
相比 Vue 2 基于 Object.defineProperty 的方案,Vue 3 在对象新增属性、数组处理等方面更自然。
4.2 为什么更新不是立刻同步打到 DOM
如果你一段逻辑里连续改三次状态,Vue 不会更新三次 DOM。
它会先把更新放进队列,再统一刷新。
4.3 nextTick 为什么存在
因为你有时需要在"DOM 已经完成这轮更新之后"再去拿真实元素。
4.4 模板编译链路
模板并不是直接在浏览器里"神奇运行"的,它大致会经历:
- Template
- 解析成 AST
- AST 转换优化
- 生成 render 函数
- render 函数生成虚拟 DOM
- runtime 负责 patch 到真实 DOM
5. 示例
5.1 nextTick 最小示例
vue
<template>
<div>
<button @click="openInput">显示输入框并聚焦</button>
<input v-if="visible" ref="inputRef" />
</div>
</template>
<script setup>
import { nextTick, ref } from 'vue'
const visible = ref(false)
const inputRef = ref(null)
const openInput = async () => {
visible.value = true
await nextTick()
inputRef.value.focus()
}
</script>
6. 工程实践
6.1 一个真实工程场景
做"可编辑表格"时,如果列表 key 写成索引,你经常会遇到:
- 删除某行后,输入框内容串位
- 某行的编辑状态跑到别的行
6.2 企业里真正常用到原理理解的地方
- 列表为什么用唯一主键。
- 为什么有些场景要用
nextTick。 - 为什么某些
computed很省性能。 - 为什么组件重渲染不等于整页重画。
7. 常见误区
- 以为 Vue 更新一定是同步的
- 把虚拟 DOM 理解成"更快的 DOM"
- 觉得
key只是为了消除警告 - 学原理只背名词
- 把所有性能问题都归因于 Vue
8. 面试题
- Vue 3 的响应式是怎么实现的?
track和trigger分别做什么?- 为什么 Vue 的 DOM 更新是异步批量的?
nextTick的使用场景是什么?- 为什么
key在 Diff 中很重要? - 模板从书写到页面渲染,中间大致经历了哪些步骤?
9. 自测题
- 你能把 Vue 的更新主链路完整说出来吗?
- 你能解释为什么连续修改状态时 Vue 不会立刻更新三次 DOM 吗?
- 你能举出一个必须依赖
nextTick的场景吗? - 你能解释"虚拟 DOM + Diff + Patch"之间的关系吗?
- 你能说明为什么模板其实最终会变成渲染函数吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 从原理层解释响应式和更新流程。
- 说清楚
key、nextTick、computed缓存的设计原因。 - 面试时不再只会背 API 名字,而是能讲运行机制。
- 对 Vue 的更新和性能有基本判断能力。
第五阶段:工程实践,真正按企业方式组织 Vue 项目
1. 学什么
这一阶段进入完整工程层,重点掌握:
Vite工程结构Vue RouterPinia- 请求封装与接口层设计
composables复用逻辑- 目录结构设计
- 环境变量与构建配置
- 组件规范、页面规范、状态规范
- 常见 UI 库接入
- 构建、部署与基本测试思维
2. 为什么重要
企业里最看重的,不只是你会写按钮和列表,而是:
- 你会不会搭项目结构
- 你会不会拆页面、路由、状态、接口
- 你会不会控制代码耦合
- 你会不会写出别人能接手的代码
3. 核心概念
3.1 推荐目录结构
text
src/
├─ api/ # 接口层
├─ assets/ # 静态资源
├─ components/ # 通用组件
├─ composables/ # 可复用组合函数
├─ router/ # 路由
├─ stores/ # Pinia 状态管理
├─ utils/ # 工具函数
├─ views/ # 页面组件
├─ App.vue
└─ main.js
3.2 路由、Store、Composables 各管什么
| 模块 | 职责 |
|---|---|
| Router | 页面导航、权限守卫、参数切换 |
| Pinia | 多组件共享状态、会话状态、缓存状态 |
| Composables | 提取可复用逻辑,如分页、请求、表单校验 |
| API 层 | 和后端交互,统一请求封装 |
3.3 什么状态该进 Pinia
适合进 Pinia 的:
- 登录用户信息
- token
- 菜单权限
- 全局主题
- 多页面共享筛选条件或缓存数据
不一定要进 Pinia 的:
- 某个弹窗的显示状态
- 某个局部表单的临时输入
- 单个组件内部只自己用的值
4. 原理解释
4.1 为什么工程里要分层
因为真实项目的复杂度,主要不是一两个组件,而是:
- 页面很多
- 数据来源很多
- 组件复用很多
- 人很多
- 需求经常变
所以工程分层的本质,是控制复杂度和边界。
4.2 为什么逻辑要抽到 composables
组合式 API 的一个核心优势,就是可以把"成套逻辑"抽成函数复用。
比如:
- 列表分页逻辑
- 请求状态逻辑
- 表单校验逻辑
- 防抖搜索逻辑
4.3 为什么接口要做统一封装
如果请求散落在页面里,后面会很难处理:
- token
- 错误提示
- loading
- 重试
- 统一 baseURL
5. 示例
5.1 最小工程片段
src/router/index.js
js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import UserView from '../views/UserView.vue'
const routes = [
{ path: '/', component: HomeView },
{ path: '/user', component: UserView }
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
src/stores/user.js
js
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useUserStore = defineStore('user', () => {
const userInfo = ref(null)
const setUserInfo = (value) => {
userInfo.value = value
}
return {
userInfo,
setUserInfo
}
})
src/main.js
js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
6. 工程实践
6.1 一个中小型项目的推荐落地步骤
- 用
Vite初始化项目。 - 配好路由和基础布局。
- 按页面和通用组件拆目录。
- 抽 API 层,统一请求工具。
- 接入 Pinia 管理共享状态。
- 抽复用逻辑到
composables。 - 增加 loading、错误态、空态。
- 统一命名、代码风格、提交规范。
6.2 一个真实工程场景
做"后台管理系统"时,通常会有这些模块:
- 登录页
- 首页仪表盘
- 用户管理
- 角色权限
- 商品管理
- 订单管理
7. 常见误区
- 把 Pinia 当作"任何状态都该放进去的仓库"
- 不抽 composables,复制业务逻辑
- 接口层和页面层不分
- 目录结构只模仿别人,不按业务边界设计
- 只管功能跑通,不管错误态和空态
8. 面试题
- Vue 项目目录一般怎么设计?
- Router、Pinia、Composables 分别适合管理什么?
- 什么时候该把状态放进 Pinia?
- 为什么请求要统一封装?
- 你会如何设计一个 Vue 后台管理系统的前端结构?
9. 自测题
- 你能独立搭一个含 Router 和 Pinia 的 Vue 项目骨架吗?
- 你能说清楚为什么局部弹窗状态通常不放全局 store 吗?
- 你能举出两个适合抽成
composables的逻辑吗? - 你能设计一个
api/、views/、components/分层明确的目录结构吗? - 你能说明 loading、空态、错误态为什么属于工程基本功吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 搭建一个 Vue 真实项目骨架。
- 合理使用 Router、Pinia、API 层、Composables。
- 按业务边界组织代码,而不是只把功能塞进组件。
- 具备中小型项目开发的基础工程视角。
第六阶段:常见问题与排错,形成稳定的调试能力
1. 学什么
这一阶段重点学习:
- Vue 页面不更新的常见原因
props修改警告排查key错误导致的列表问题reactive解构导致响应式丢失watch死循环nextTick时机问题- 路由参数变化但页面逻辑未更新
- 异步请求竞态
- 样式作用域与样式污染
- DevTools 和日志调试思路
2. 为什么重要
企业里真正拉开差距的,往往不是"能不能写一个功能",而是:
- 功能出了问题你能不能快速定位
- 线上问题你能不能稳定修
- 你能不能把 bug 归因到状态、模板、生命周期、异步还是工程结构
3. 核心概念
3.1 常见症状与原因对照表
| 症状 | 常见原因 | 第一检查点 |
|---|---|---|
| 数据变了但页面不更新 | 响应式丢失、直接改了非响应式值 | 是否用了 ref / reactive |
| 列表删除后输入框串位 | key 用错 |
是否用了稳定唯一 id |
子组件报 props 修改警告 |
直接改了父传入值 | 是否应该 emit 回父组件 |
| DOM 取不到最新元素 | 更新还没完成 | 是否需要 nextTick |
| 搜索结果错乱 | 异步竞态 | 是否取消旧请求或比对请求序号 |
| 页面切路由参数后没刷新 | 组件复用导致逻辑未重新触发 | 是否监听路由参数变化 |
3.2 一个排错主线
- 状态有没有变
- 变的是不是响应式状态
- 模板有没有依赖这个状态
- 组件有没有被复用或缓存
- 更新时机是不是还没到
- 是否被异步请求覆盖
4. 原理解释
4.1 为什么会出现"数据变了页面不变"
最常见不是 Vue 不工作,而是:
- 你改的不是响应式数据
- 你把
reactive对象错误解构后失去追踪 - 模板根本没依赖这个值
4.2 为什么异步请求会造成显示错乱
比如你快速输入搜索词:
- 先发请求 A
- 再发请求 B
- B 先回来
- A 后回来覆盖了 B 的结果
4.3 为什么路由切了参数,组件却不重新创建
因为很多时候路由是复用同一个组件实例,只是参数变了。
所以如果你的逻辑只写在 onMounted,参数变了也不会自动再跑。
5. 示例
5.1 响应式丢失示例
错误写法:
js
import { reactive } from 'vue'
const state = reactive({
count: 0
})
const { count } = state
count++
更合理的写法:
js
import { reactive, toRefs } from 'vue'
const state = reactive({
count: 0
})
const { count } = toRefs(state)
count.value++
6. 工程实践
6.1 通用排错步骤
- 打日志看数据是否变化。
- 用 Vue DevTools 看组件状态。
- 确认模板是否真的消费了该状态。
- 检查
key、生命周期、路由参数、缓存组件。 - 检查异步请求顺序和覆盖关系。
- 最后再怀疑框架或库本身。
6.2 一个真实工程场景
做"用户搜索页"时,输入框快速输入会导致结果闪烁或回退。
解决思路通常是:
- 做防抖
- 记录最新请求编号
- 或取消旧请求
7. 常见误区
- 页面没更新就先怀疑 Vue
- 一出 bug 就到处加
nextTick - 日志只看接口返回,不看状态流转
- 不复盘 bug 根因
- 把排错当经验主义
8. 面试题
- Vue 中"数据更新了但页面没更新"可能有哪些原因?
- 为什么不推荐解构
reactive对象后直接使用? - 列表为什么不建议用索引做
key? nextTick常见误用有哪些?- 路由参数变化但组件不重新请求数据,你会怎么排查?
9. 自测题
- 你能给出一个响应式丢失的例子并修复吗?
- 你能描述一个列表错位 bug 的根因吗?
- 你能说明为什么某些路由切换后页面没有重新请求吗?
- 你能给出一个避免异步竞态的策略吗?
- 你能写出自己的 Vue 排错步骤清单吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 独立排查大多数基础到中级 Vue 问题。
- 知道 bug 是状态问题、时机问题、通信问题还是异步问题。
- 面试中能回答"怎么排错",不只是"怎么用"。
第七阶段:面试与评估,把知识变成可表达、可回答、可证明的能力
1. 学什么
这一阶段重点学习:
- Vue 高频面试题分类
- 面试回答结构
- 概念题、原理题、工程题、排错题的答法
- 如何讲自己的 Vue 项目
- 如何把"会用"升级成"会解释"
2. 为什么重要
面试不是背书比赛,而是在判断你是否真正理解、是否做过、是否能在团队里承担工作。
面试官尤其关注三点:
- 你能否讲清楚因果关系。
- 你能否把原理落到代码和项目。
- 你是否有稳定的工程判断,而不是只会背八股。
3. 核心概念
3.1 四类问题怎么区分
| 类型 | 面试官想看什么 | 回答重点 |
|---|---|---|
| 概念题 | 你是否知道基础定义 | 先定义,再场景 |
| 原理题 | 你是否理解底层机制 | 先流程,再设计原因 |
| 工程题 | 你是否做过真实项目 | 先场景,再架构与权衡 |
| 排错题 | 你是否能解决问题 | 先定位思路,再给方案 |
3.2 一个通用回答模板
- 先给一句定义
- 说它解决什么问题
- 说核心机制
- 说典型场景
- 说常见坑或设计权衡
3.3 容易混淆的高频对比
| 对比项 | 关键区别 |
|---|---|
computed vs watch |
一个算派生值,一个做副作用 |
ref vs reactive |
一个包单值,一个代理对象 |
v-if vs v-show |
一个控制创建销毁,一个控制显示隐藏 |
props vs Pinia |
一个是近距离通信,一个是共享状态管理 |
watch vs watchEffect |
一个显式监听源,一个自动收集依赖 |
4. 原理解释
4.1 为什么面试官喜欢追问"为什么"
因为"怎么用"可以靠记忆,"为什么这样设计"更能体现:
- 你是否真正理解
- 你是否有迁移能力
- 你能否在新场景中做判断
4.2 一个标准答案应该长什么样
以"computed 和 watch 区别"为例:
computed用于根据已有响应式数据推导新值,带缓存,适合展示层派生状态。watch用于监听某个值变化后执行副作用,比如发请求、同步本地存储。- 如果本质是公式关系,用
computed;如果本质是变化触发外部动作,用watch。
5. 示例
5.1 一个高频面试题示范回答
题目:Vue 为什么要使用 key?
参考答法:
key的核心作用是给虚拟 DOM 中的节点提供稳定身份,方便 Diff 过程正确复用和移动节点。如果没有稳定
key,或者直接用索引,当列表发生插入、删除、重排时,Vue 可能会错误复用 DOM,导致输入框串位、本地状态错乱等问题。所以在动态列表里,应该优先使用业务稳定唯一 id 作为
key。
6. 工程实践
6.1 如何讲项目
讲 Vue 项目时,不要只说"我做了登录页和列表页",而要按下面顺序:
- 项目是做什么的
- 技术栈是什么
- 你负责的模块是什么
- 页面和状态是怎么组织的
- 遇到过什么问题
- 你怎么优化或排错的
6.2 一个真实工程场景
比如你做了"后台管理系统",可以这样讲:
- 我用
Vue 3 + Vite + Vue Router + Pinia搭建前端项目。 - 负责了用户管理、角色权限、订单列表模块。
- 页面层和通用组件层做了拆分,接口层做了统一封装。
- 对搜索列表做了防抖和请求竞态控制。
- 对表单弹窗用
props / emit管理局部状态,全局用户信息放 Pinia。
7. 常见误区
- 只背定义,不会讲场景
- 只讲"我做了什么",不讲"为什么这样设计"
- 只讲 happy path,不讲问题和权衡
- 面试题回答过短
- 面试题回答过散
8. 面试题
- Vue 3 和 Vue 2 在响应式实现上有什么差异?
computed和watch的区别是什么?nextTick的作用和场景是什么?- 你会如何设计一个 Vue 后台管理项目的结构?
- Pinia 和组件局部状态应该怎么划分边界?
9. 自测题
- 你能在 3 分钟内解释清楚 Vue 响应式原理吗?
- 你能在 2 分钟内解释清楚
computed和watch的区别吗? - 你能用项目场景说明什么时候要用 Pinia 吗?
- 你能讲出一个列表
key用错导致的 bug 吗? - 你能把一个项目经验讲成"场景 -> 设计 -> 问题 -> 解决"的结构吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 系统回答 Vue 基础到中级面试题。
- 用原理、场景、权衡三个层次组织答案。
- 把项目经验讲得具体、可信、可追问。
第八阶段:学习总结与知识闭环,从会写到持续进阶
1. 学什么
这一阶段的重点不再是新 API,而是:
- 如何把 Vue 知识串成体系
- 如何通过项目闭环巩固能力
- 如何继续进阶到中级甚至更高
- 如何建立长期学习方法
2. 为什么重要
很多人学到这里会出现两个问题:
- 学了很多点,但串不起来
- 会做练习题,但做项目容易散架
3. 核心概念
3.1 Vue 的知识主干
你现在应该把 Vue 理解成下面这棵树:
- 最上层是页面与业务需求。
- 第二层是组件化和状态管理。
- 第三层是响应式、生命周期、通信机制。
- 第四层是编译、调度、虚拟 DOM、Diff 等底层原理。
- 外围是 Router、Pinia、请求层、构建、测试、部署等工程体系。
3.2 学习本质
Vue 学习不是"背多少 API",而是:
- 能不能把页面拆成组件
- 能不能把业务拆成状态
- 能不能把状态变化映射为界面变化
- 能不能把项目组织成可维护工程
- 能不能排错和解释
3.3 下一步进阶方向
| 方向 | 为什么值得继续学 |
|---|---|
| TypeScript | 企业 Vue 项目中非常常见 |
| Nuxt | SSR、SEO、全栈能力 |
| VueUse | 提高组合式逻辑复用效率 |
| 测试 | 单元测试、组件测试、端到端测试 |
| 性能优化 | 大列表、懒加载、缓存、渲染边界 |
| 源码 | 从会用走向深入理解框架设计 |
4. 原理解释
4.1 为什么项目是最好的复习方式
因为项目会逼你把分散知识点串起来:
- 模板语法
- 响应式
- 路由
- 状态管理
- 请求
- 错误处理
- 组件复用
- 排错
4.2 正确的复习路径
- 回顾阶段 2 和阶段 3,确保 API 和心智模型稳定。
- 回顾阶段 4,确保能解释关键原理。
- 用阶段 5 的工程方式做项目。
- 用阶段 6 的排错方法复盘问题。
- 用阶段 7 的答题方法做口头表达训练。
5. 示例
5.1 一个完整项目闭环示例
建议你做一个"任务管理系统",至少包含:
- 登录页
- 任务列表页
- 任务筛选和搜索
- 新增 / 编辑 / 删除任务
- 任务状态切换
- 路由切换
- Pinia 管理用户信息
- 接口层封装或本地 mock
6. 工程实践
6.1 推荐的 4 周推进法
- 第 1 周:完成阶段 1 到阶段 3 的示例和练习。
- 第 2 周:补完阶段 4,开始写小项目。
- 第 3 周:按阶段 5 的方式把小项目工程化。
- 第 4 周:做排错复盘和模拟面试。
6.2 企业里继续深入会学什么
- TypeScript + Vue 3
- 权限系统与动态路由
- 组件库封装
- 大列表性能优化
- 单元测试与 E2E 测试
- SSR / Nuxt
7. 常见误区
- 教程看很多,项目做很少
- 写完项目不复盘
- 只学功能,不学排错
- 只学 Vue,不补 JavaScript 和工程基础
8. 面试题
- 学完 Vue 核心后,你下一步会深入什么,为什么?
- 如果让你从零搭一个 Vue 项目,你会按什么顺序做?
- 你如何判断自己从初学者进入了初级 / 中级水平?
- Vue 项目里你最常见的 bug 类型是什么?你如何建立预防机制?
9. 自测题
- 你能把 Vue 的知识主干画出来吗?
- 你能给自己设计一个 4 周 Vue 学习计划吗?
- 你能用一个项目串起模板、响应式、路由、Pinia、请求封装吗?
- 你能清楚说出自己目前最薄弱的是语法、原理、工程还是排错吗?
10. 学完标志
学完这一阶段后,你应该能做到:
- 把 Vue 核心知识讲成一个完整体系。
- 用项目把知识点串起来,而不是零散记忆。
- 明确自己下一步该补什么。
- 形成持续迭代、自测、复盘的学习闭环。
评估体系
1. 入门达标标准
达到入门,至少应满足:
- 知道 Vue 是什么,能解释"状态驱动 UI"。
- 会创建并运行一个 Vue 项目。
- 会写
ref、事件绑定、条件渲染、列表渲染。 - 能完成一个计数器或待办列表。
2. 初级达标标准
达到初级,至少应满足:
- 会写组件,能用
props / emit通信。 - 能正确使用
computed、watch、生命周期。 - 会使用 Vue Router 和 Pinia 做基础项目。
- 能完成一个中小型页面模块。
- 能解决常见基础 bug。
3. 中级达标标准
达到中级,至少应满足:
- 能解释响应式、调度、虚拟 DOM、Diff 的主链路。
- 能按工程方式组织项目目录、接口层、状态层、路由层。
- 能处理常见异步竞态、列表 key、响应式丢失、生命周期时机问题。
- 能讲清楚项目设计选择和取舍。
- 能比较稳定地应对基础到中级 Vue 面试。
4. 一套自测题
- Vue 为什么说是"声明式 UI 框架"?
ref和reactive有什么区别?computed和watch的区别是什么?v-if和v-show分别适合什么场景?- 为什么
v-for需要key? - 子组件为什么不应该直接修改
props? onMounted和onUnmounted常用于做什么?nextTick的作用是什么?- Pinia 适合管理什么状态?
- Vue 中"数据变了页面不更新"你会如何排查?
- 路由参数变化但页面不更新,你会怎么处理?
- Vue 模板最终为什么能变成页面?
5. 一套面试题
- Vue 3 响应式原理是怎样的?
computed为什么有缓存?和方法调用有什么区别?- 说说你对
watch、watchEffect的理解。 - 为什么 Vue 的 DOM 更新通常不是同步立即执行的?
nextTick的底层价值是什么?- 虚拟 DOM 的意义是什么?
key在 Diff 中扮演什么角色?- 你会如何拆分一个复杂页面的组件?
- 你会如何设计一个 Vue 后台管理系统?
- 什么时候用
props / emit,什么时候用 Pinia? - 你在 Vue 项目里遇到过什么典型 bug?如何定位?
- Vue 3 相比 Vue 2,你觉得最重要的变化是什么?
6. 一套实战任务
实战任务用于验证"会写页面 + 会组织状态":
- 实现一个待办事项应用,支持增删改查、状态筛选、关键字搜索。
- 用组件拆分成输入区、列表区、筛选区。
- 使用
computed实现筛选结果。 - 使用
watch把搜索词同步到本地存储。 - 给动态列表使用稳定
key。 - 页面加入空态提示和删除确认。
7. 一套项目任务
项目名称:任务管理后台系统
最低要求:
- 使用
Vue 3 + Vite + Vue Router + Pinia。 - 包含登录页、任务列表页、任务详情页。
- 支持筛选、分页、搜索、新增、编辑、删除。
- 有统一 API 层或 mock 数据层。
- 有 loading、错误态、空态。
- 路由和页面结构清晰。
- 能讲清楚状态边界、组件拆分和请求流程。
加分项:
- 使用 TypeScript。
- 使用 composables 抽分页或请求逻辑。
- 处理请求竞态。
- 做基础权限控制。
- 写一部分测试。
8. 对你回答的评分标准
总分 100,建议按下面维度评分:
| 维度 | 分值 | 评分标准 |
|---|---|---|
| 基础概念 | 20 | 是否能清楚解释核心术语 |
| 代码能力 | 25 | 是否能独立写出常用页面和组件 |
| 原理理解 | 20 | 是否能解释响应式、更新、Diff 等主链路 |
| 工程实践 | 15 | 是否会用 Router、Pinia、API 分层 |
| 排错能力 | 10 | 是否有清晰定位步骤 |
| 面试表达 | 10 | 是否能讲清楚定义、场景、原理、权衡 |
参考分段:
- 0 到 59:知识零散,项目和面试都不稳定。
- 60 到 74:达到入门,可写简单页面。
- 75 到 84:达到初级,可做中小模块。
- 85 到 100:接近中级,具备解释、工程、排错综合能力。
9. 如何根据错误结果反向补课
| 你错在哪类题 | 说明短板在哪 | 回补阶段 |
|---|---|---|
| 模板语法、组件基础题 | 页面表达能力不足 | 第二阶段 |
ref、reactive、computed、生命周期题 |
状态和机制没吃透 | 第三阶段 |
响应式原理、nextTick、key、Diff 题 |
原理理解不足 | 第四阶段 |
| Router、Pinia、目录结构、API 分层题 | 工程化能力不足 | 第五阶段 |
| 页面不更新、竞态、路由复用题 | 排错能力不足 | 第六阶段 |
| 项目讲不清、答案发散 | 面试表达不足 | 第七阶段 |
进一步的补课方法:
- 概念不会:回到对应阶段,重写定义并举一个自己的例子。
- 代码不会:重写该阶段最小示例,要求不看资料完成。
- 原理不会:把运行流程画成步骤图,再口头讲一遍。
- 工程不会:按第五阶段重新搭一个最小项目骨架。
- 排错不会:故意制造一个 bug,再按第六阶段流程定位。
- 面试不会:录音回答高频题,听自己是否只会背定义。
10. 最终闭环执行方案
建议你按下面方式执行这份文档:
- 完成第一到第三阶段,建立 Vue 核心使用能力。
- 完成第四阶段,把 API 背后的原理串起来。
- 完成第五阶段,用工程方式做一个项目骨架。
- 完成第六阶段,主动制造并修复几个典型 bug。
- 完成第七阶段,做一次模拟面试。
- 完成第八阶段,交付一个完整项目并复盘。
到这里,你对 Vue 的掌握就不再是"看过教程",而是更接近:
- 能理解
- 能解释
- 能上手
- 能排错
- 能通过基础到中级面试