【个人学习||vue】vue

学习地图

这门学科是干什么的

Vue 是一个用于构建用户界面的前端框架。它最核心的事情只有一句话:**让页面随着数据变化而自动更新**。

你真正要学的,不只是几个 API,而是三件事:

  1. 用"组件"拆页面。

  2. 用"状态"驱动界面。

  3. 用"工程化方式"组织前端项目。

**学习本质:必须吃透**

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 | 服务端渲染与全栈能力 | 先知道,后深入 |

学它之前需要哪些前置知识

建议至少具备下面这些基础,不需要很深,但要会用:

  1. HTML 基础:标签、表单、列表、语义化。

  2. CSS 基础:选择器、盒模型、Flex、定位。

  3. JavaScript 基础:变量、函数、对象、数组、作用域。

  4. ES6 常用语法:模块化、解构、模板字符串、Promise、async/await。

  5. 浏览器基础:DOM、事件冒泡、默认行为、网络请求。

  6. 命令行基础:`cd`、`npm install`、`npm run dev`。

如果你现在 JS 还不熟,学习顺序一定是:**先补 JS 常用语法,再学 Vue**。

因为 Vue 的难点,很多时候并不是框架本身,而是 JS、组件思维和异步思维。

真正重要的 20% 核心内容是什么

下面这些内容,占了 Vue 实战和面试里最有价值的 80%:

  1. **组件化思维**:怎么拆页面、怎么复用组件。

  2. **模板语法与指令**:插值、`v-bind`、`v-model`、`v-if`、`v-for`、事件绑定。

  3. **响应式数据**:`ref`、`reactive`、数据变化为什么会驱动视图更新。

  4. **组件通信**:`props`、`emit`、`provide / inject`、状态管理的适用边界。

  5. **计算属性与侦听器**:`computed`、`watch`、`watchEffect` 的区别和场景。

  6. **生命周期**:什么时候发请求、什么时候操作 DOM、什么时候清理副作用。

  7. **路由与页面组织**:Vue Router 的路由匹配、导航、嵌套路由、守卫。

  8. **状态管理**:Pinia 如何管理全局状态。

  9. **接口请求与异步状态处理**:加载中、错误态、空态、重试。

  10. **基础排错能力**:组件不更新、`key` 用错、响应式丢失、`props` 误改、`nextTick` 误用。

哪些内容是初学者容易陷入、但不值得一开始深挖的

这些内容不是不重要,而是不该在最开始投入过多时间:

  1. Vue 源码逐行阅读。

  2. 编译器细节,比如模板 AST 的每个转换过程。

  3. 自定义渲染器。

  4. SSR / Nuxt 的复杂部署。

  5. 极限性能优化和复杂构建链魔改。

  6. 太早陷入"Vue 2 和 Vue 3 所有差异背诵"。

  7. 太早陷入"所有生态库全都学一遍"。

建议原则:

  • **必须掌握**:组件、响应式、通信、生命周期、路由、状态管理、排错。

  • **知道即可**:SSR、宏观源码架构、编译器实现细节、高阶性能调优。

设计哲学

Vue 的设计哲学可以概括成三句话:

  1. **渐进式**:你可以从一页小功能开始用,也可以做完整工程项目。

  2. **声明式**:你描述"页面应该长什么样",不是手写每一次 DOM 修改过程。

  3. **组合式**:逻辑按能力组织,而不是按生命周期函数强行分散。


学习顺序

下面是推荐的学习顺序,也是企业里最接近真实成长路径的一条线:

  1. **第一阶段:入门认知**

理解 Vue 在前端中的角色,能跑起第一个应用,知道"为什么页面会自动更新"。

  1. **第二阶段:核心语法与组件**

掌握模板语法、指令、组件、`props`、事件、表单、列表、条件渲染。

  1. **第三阶段:响应式与组件通信机制**

吃透 `ref`、`reactive`、`computed`、`watch`、生命周期,以及父子、兄弟、跨层通信。

  1. **第四阶段:底层原理**

理解响应式追踪、依赖收集、调度更新、虚拟 DOM、Diff、`nextTick`、模板编译链路。

  1. **第五阶段:工程实践**

会用 Vite、Vue Router、Pinia、接口封装、目录结构、组件规范、环境配置、构建发布。

  1. **第六阶段:常见问题与排错**

能定位"不更新""重复渲染""路由失效""状态丢失""样式污染""异步竞态"等问题。

  1. **第七阶段:面试与评估**

把知识整理成可以解释、可以对比、可以落到代码和场景的答案。

  1. **第八阶段:项目闭环**

完成一个中小型项目,把知识点串起来,形成"会做 + 会讲 + 会排错"的能力。

正确学习顺序为什么是这样

因为 Vue 学偏最常见的原因有两个:

  1. 一开始背 API,不理解"状态驱动视图"。

  2. 一开始啃源码,却没有真实业务问题作为抓手。

所以正确路径一定是:

**先直觉认知 -> 再掌握常用 API -> 再理解机制 -> 再进入工程与源码。**

企业里通常怎么用 Vue

企业里最常见的组合是:

  • `Vue 3 + Vite`

  • `Vue Router`

  • `Pinia`

  • `Axios / Fetch`

  • `Element Plus / Ant Design Vue / 自研组件库`

  • `TypeScript`(很多团队会加)

面试官通常怎么问

初级到中级 Vue 面试,常见问法通常分四类:

  1. 概念类:Vue 是什么?响应式是什么?`computed` 和 `watch` 区别是什么?

  2. 机制类:Vue 为什么更新快?`nextTick` 是干什么的?`key` 为什么重要?

  3. 工程类:项目怎么拆组件?如何管理公共状态?接口如何封装?

  4. 排错类:为什么页面不更新?为什么列表复用有问题?为什么子组件不能直接改 `props`?


自循环推进规则

从这里开始,这份文档不再依赖"回复继续"才能往下学,而是按下面的闭环自动推进:

  1. 先学当前阶段的主干内容。

  2. 跑通当前阶段的最小示例。

  3. 完成当前阶段的练习题或工程任务。

  4. 对照当前阶段的"学完标志"和"验收标准"自测。

  5. 如果自测正确率在 80% 以上,直接进入下一阶段。

  6. 如果自测正确率低于 80%,先按文末"反向补课"回补,再继续推进。

建议学习节奏:

  1. 第一到第三阶段:重在建立正确直觉和常用写法。

  2. 第四到第六阶段:重在理解为什么这样设计,以及怎么排错。

  3. 第七到第八阶段:重在把知识变成面试表达和项目能力。

你可以把这份文档当成一个可循环执行的学习流程:

`学概念 -> 写示例 -> 做练习 -> 自测 -> 查漏补缺 -> 进入下一阶段 -> 项目闭环`


第一阶段:Vue 到底是什么,为什么它能让页面跟着数据走

1. 学什么

这一阶段你要建立三个最重要的直觉:

  1. Vue 不是"一个会写页面的语法糖",而是一个**状态驱动 UI 的框架**。

  2. Vue 的基本单位是**组件**,不是一整页代码。

  3. 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 页面时,大致发生了下面这些事情:

  1. `createApp()` 创建一个应用实例。

  2. `mount('#app')` 把应用挂到页面上的某个容器。

  3. Vue 读取模板,建立"模板依赖了哪些数据"的关系。

  4. 你在 `setup()` 里定义响应式数据,比如 `ref(0)`。

  5. 模板使用了这个数据,比如 `{{ count }}`。

  6. 当 `count` 变化时,Vue 知道这个值被页面依赖了。

  7. Vue 不会粗暴整页重画,而是找到需要更新的部分,补丁式更新 DOM。

4.2 为什么这样设计

Vue 这样设计,是为了同时解决三个问题:

  1. **开发效率**:不再每次都手动改 DOM。

  2. **可维护性**:页面逻辑以组件和状态组织,更清晰。

  3. **性能平衡**:通过依赖追踪和批量调度,避免无意义重渲染。

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 的做法会是:

  1. 把页面拆成列表组件、搜索组件、弹窗组件。

  2. 把"学生数据"和"当前筛选条件"作为状态。

  3. 模板根据状态自动渲染结果。

  4. 用户点击按钮,实际改的是状态,不是手动改一堆 DOM。

7. 常见误区

  1. **把 Vue 当成模板拼接工具**

  2. **上来就背很多 API**

  3. **在 Vue 里还习惯手动操作 DOM**

  4. **分不清 `ref` 和普通变量**

  5. **一开始就沉迷源码**

  6. **学 Vue 却不补 JavaScript**

8. 面试题

  1. Vue 是什么?它解决了什么问题?

  2. 什么是声明式开发?

  3. Vue 为什么能在数据变化时自动更新页面?

  4. `ref` 是什么?为什么模板里不用写 `.value`?

  5. `createApp().mount()` 做了什么?

9. 自测题

  1. 用你自己的话解释:为什么说 Vue 是"状态驱动 UI"的框架?

  2. 原生 DOM 手动更新页面,和 Vue 响应式更新页面,本质差别是什么?

  3. `ref(0)` 和 `let count = 0` 在 Vue 组件里有什么本质区别?

  4. `createApp`、`setup`、`mount` 分别负责什么?

  5. 为什么说组件是 Vue 项目的基本组织单位?

  6. 如果点击按钮后数据变了,但页面没变,你第一反应应该检查什么?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 用自己的话解释 Vue 是什么,以及它为什么比手动 DOM 操作更适合复杂页面。

  2. 说清楚"声明式开发""组件""响应式"的含义。

  3. 独立跑起一个 Vue 项目。

  4. 写出一个最小可运行组件,包含数据、事件和条件渲染。

  5. 初步解释"为什么数据变了,页面会跟着变"。


第一阶段练习题

练习 1:计数器增强版

要求你实现:

  1. 一个数字计数器。

  2. 一个"加 1"按钮。

  3. 一个"减 1"按钮。

  4. 一个"重置"按钮。

  5. 当数字大于等于 5 时显示提示文字。

  6. 当数字小于 0 时,文字变成红色。

练习 2:个人信息卡片

要求你实现:

  1. 页面展示姓名、年龄、职业。

  2. 点击按钮后年龄加 1。

  3. 点击按钮切换"在职 / 离职"状态。

  4. 用条件渲染显示不同文案。

练习 3:待办事项最小版

要求你实现:

  1. 输入框输入待办内容。

  2. 点击按钮新增一条待办。

  3. 页面显示待办列表。

  4. 每条待办旁边有删除按钮。

第一阶段验收标准

如果你能独立完成上面 3 个练习中的至少 2 个,并且能口头回答下面这 4 个问题,就算第一阶段基本达标:

  1. Vue 为什么适合做复杂前端页面?

  2. 什么是响应式数据?

  3. 为什么我们更推荐"改状态"而不是"手动改 DOM"?

  4. 一个 Vue 项目最基本是怎么启动起来的?


第二阶段:模板语法、组件拆分与页面表达

1. 学什么

这一阶段开始真正进入"会写页面"的部分,重点掌握:

  1. 插值表达式 `{{ }}`

  2. 属性绑定 `v-bind`

  3. 事件绑定 `v-on`

  4. 表单双向绑定 `v-model`

  5. 条件渲染 `v-if`、`v-else-if`、`v-else`、`v-show`

  6. 列表渲染 `v-for`

  7. 列表更新中的 `key`

  8. 单文件组件 `*.vue`

  9. 基础组件拆分

  10. `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` 为什么是语法糖

它本质上是两件事的组合:

  1. 把值绑定到表单元素上。

  2. 在输入变化时同步回数据。

你可以把它理解成:

```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 实际开发操作步骤

  1. 先画出页面结构。

  2. 判断哪些是静态部分,哪些是动态部分。

  3. 找出页面状态:输入值、列表数据、当前选中项、显示隐藏状态。

  4. 决定哪些内容放父组件,哪些拆成子组件。

  5. 用 `props` 传数据,用 `emit` 回传事件。

  6. 给列表项补稳定 `key`。

  7. 最后再考虑样式和细节交互。

6.2 一个真实工程场景

比如做"商品列表页":

  • 父组件负责:关键词、筛选项、商品数组、请求状态。

  • 搜索栏组件负责:输入和点击搜索。

  • 商品卡片组件负责:展示单个商品信息。

  • 分页组件负责:页码切换。

7. 常见误区

  1. **把所有东西都写在一个组件里**

  2. **子组件直接修改 `props`**

  3. **`v-for` 用索引当 `key`**

  4. **把 `v-if` 和 `v-for` 写在同一个节点上**

  5. **认为 `v-model` 是"Vue 黑魔法"**

8. 面试题

  1. `v-if` 和 `v-show` 有什么区别?分别适合什么场景?

  2. `v-model` 的本质是什么?

  3. 为什么 `v-for` 需要 `key`?如果不用会怎样?

  4. 父子组件怎么通信?

  5. 为什么子组件不能直接修改 `props`?

9. 自测题

  1. 你能不用看资料写出 `v-bind`、`v-model`、`v-for` 的基本用法吗?

  2. 你能说清楚 `v-if` 和 `v-show` 的性能差异吗?

  3. 你能独立把一个页面拆成父组件和两个子组件吗?

  4. 你能解释为什么 `key` 应该用稳定唯一值吗?

  5. 如果子组件点击删除按钮,你知道为什么更推荐用 `emit` 通知父组件,而不是子组件直接删数据吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 用 Vue 写出表单、列表、条件显示页面。

  2. 独立完成基础组件拆分。

  3. 正确使用 `props` 和 `emit` 完成父子通信。

  4. 说清楚 `v-if`、`v-show`、`v-model`、`v-for`、`key` 的场景和原理直觉。


第三阶段:响应式、生命周期与组件通信机制

1. 学什么

这一阶段进入 Vue 的核心能力层,重点是:

  1. `ref` 和 `reactive`

  2. `computed`

  3. `watch` 和 `watchEffect`

  4. 生命周期钩子

  5. 父子、兄弟、跨层组件通信

  6. `provide / inject`

  7. 共享状态该什么时候上 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 生命周期为什么存在

因为组件不是永远静止的,它有自己的运行过程:

  1. 创建

  2. 渲染

  3. 挂载到 DOM

  4. 更新

  5. 卸载

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 实战中的选择原则

  1. 页面展示用到的原始值,放 `ref` 或 `reactive`。

  2. 所有"由已有值推出来的新值",优先考虑 `computed`。

  3. 所有"监听变化后要去做外部动作"的逻辑,才考虑 `watch`。

  4. 接口首屏加载常放在 `onMounted`。

  5. 定时器、订阅、全局事件监听,在 `onUnmounted` 里清理。

6.2 一个真实工程场景

做"订单列表页"时常见状态有:

  • 查询条件

  • 当前页码

  • 订单列表

  • 加载中状态

  • 总数

7. 常见误区

  1. **用 `watch` 代替 `computed`**

  2. **所有对象都用 `reactive`,所有值都混着写**

  3. **忘记清理副作用**

  4. **任何共享数据都塞进全局 store**

  5. **误以为 `watchEffect` 是更高级的 `watch`**

8. 面试题

  1. `ref` 和 `reactive` 有什么区别?

  2. `computed` 和 `watch` 的区别是什么?

  3. 什么时候用 `watchEffect`?

  4. Vue 生命周期最常用的是哪些?分别适合做什么?

  5. 如果多个组件都依赖同一份状态,你会怎么设计?

9. 自测题

  1. 你能举出三个必须用 `computed` 而不该用 `watch` 的场景吗?

  2. 你能解释为什么"搜索结果数量"适合 `computed` 吗?

  3. 你能说出 `onMounted` 和 `onUnmounted` 各自处理哪类逻辑吗?

  4. 你能给一个"局部状态不该放 Pinia"的例子吗?

  5. 你能不用资料写出一个 `watch` 监听输入框并同步本地存储的例子吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 正确区分原始状态、派生状态、副作用。

  2. 正确使用 `ref`、`reactive`、`computed`、`watch`。

  3. 知道请求、DOM 操作、清理逻辑该放在哪个生命周期。

  4. 能为父子通信、跨层通信、共享状态选择合理方案。


第四阶段:底层原理,理解 Vue 为什么这样设计

1. 学什么

这一阶段是从"会用"走向"能解释"的关键层,重点包括:

  1. 响应式原理:`Proxy`、依赖收集、触发更新

  2. `effect`、`track`、`trigger`

  3. 调度更新与批量刷新

  4. `nextTick`

  5. 虚拟 DOM

  6. Diff 与 `key`

  7. 模板编译流程

  8. 为什么 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 运行流程图

```mermaid

graph TD

A["响应式数据被读取"] --> B["track: 收集依赖"]

B --> C["数据发生变化"]

C --> D["trigger: 通知依赖"]

D --> E["调度器合并更新"]

E --> F["重新生成虚拟 DOM"]

F --> G["Diff 比较新旧节点"]

G --> H["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 模板编译链路

模板并不是直接在浏览器里"神奇运行"的,它大致会经历:

  1. Template

  2. 解析成 AST

  3. AST 转换优化

  4. 生成 render 函数

  5. render 函数生成虚拟 DOM

  6. 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 企业里真正常用到原理理解的地方

  1. 列表为什么用唯一主键。

  2. 为什么有些场景要用 `nextTick`。

  3. 为什么某些 `computed` 很省性能。

  4. 为什么组件重渲染不等于整页重画。

7. 常见误区

  1. **以为 Vue 更新一定是同步的**

  2. **把虚拟 DOM 理解成"更快的 DOM"**

  3. **觉得 `key` 只是为了消除警告**

  4. **学原理只背名词**

  5. **把所有性能问题都归因于 Vue**

8. 面试题

  1. Vue 3 的响应式是怎么实现的?

  2. `track` 和 `trigger` 分别做什么?

  3. 为什么 Vue 的 DOM 更新是异步批量的?

  4. `nextTick` 的使用场景是什么?

  5. 为什么 `key` 在 Diff 中很重要?

  6. 模板从书写到页面渲染,中间大致经历了哪些步骤?

9. 自测题

  1. 你能把 Vue 的更新主链路完整说出来吗?

  2. 你能解释为什么连续修改状态时 Vue 不会立刻更新三次 DOM 吗?

  3. 你能举出一个必须依赖 `nextTick` 的场景吗?

  4. 你能解释"虚拟 DOM + Diff + Patch"之间的关系吗?

  5. 你能说明为什么模板其实最终会变成渲染函数吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 从原理层解释响应式和更新流程。

  2. 说清楚 `key`、`nextTick`、`computed` 缓存的设计原因。

  3. 面试时不再只会背 API 名字,而是能讲运行机制。

  4. 对 Vue 的更新和性能有基本判断能力。


第五阶段:工程实践,真正按企业方式组织 Vue 项目

1. 学什么

这一阶段进入完整工程层,重点掌握:

  1. `Vite` 工程结构

  2. `Vue Router`

  3. `Pinia`

  4. 请求封装与接口层设计

  5. `composables` 复用逻辑

  6. 目录结构设计

  7. 环境变量与构建配置

  8. 组件规范、页面规范、状态规范

  9. 常见 UI 库接入

  10. 构建、部署与基本测试思维

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 为什么工程里要分层

因为真实项目的复杂度,主要不是一两个组件,而是:

  1. 页面很多

  2. 数据来源很多

  3. 组件复用很多

  4. 人很多

  5. 需求经常变

所以工程分层的本质,是**控制复杂度和边界**。

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 一个中小型项目的推荐落地步骤

  1. 用 `Vite` 初始化项目。

  2. 配好路由和基础布局。

  3. 按页面和通用组件拆目录。

  4. 抽 API 层,统一请求工具。

  5. 接入 Pinia 管理共享状态。

  6. 抽复用逻辑到 `composables`。

  7. 增加 loading、错误态、空态。

  8. 统一命名、代码风格、提交规范。

6.2 一个真实工程场景

做"后台管理系统"时,通常会有这些模块:

  • 登录页

  • 首页仪表盘

  • 用户管理

  • 角色权限

  • 商品管理

  • 订单管理

7. 常见误区

  1. **把 Pinia 当作"任何状态都该放进去的仓库"**

  2. **不抽 composables,复制业务逻辑**

  3. **接口层和页面层不分**

  4. **目录结构只模仿别人,不按业务边界设计**

  5. **只管功能跑通,不管错误态和空态**

8. 面试题

  1. Vue 项目目录一般怎么设计?

  2. Router、Pinia、Composables 分别适合管理什么?

  3. 什么时候该把状态放进 Pinia?

  4. 为什么请求要统一封装?

  5. 你会如何设计一个 Vue 后台管理系统的前端结构?

9. 自测题

  1. 你能独立搭一个含 Router 和 Pinia 的 Vue 项目骨架吗?

  2. 你能说清楚为什么局部弹窗状态通常不放全局 store 吗?

  3. 你能举出两个适合抽成 `composables` 的逻辑吗?

  4. 你能设计一个 `api/`、`views/`、`components/` 分层明确的目录结构吗?

  5. 你能说明 loading、空态、错误态为什么属于工程基本功吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 搭建一个 Vue 真实项目骨架。

  2. 合理使用 Router、Pinia、API 层、Composables。

  3. 按业务边界组织代码,而不是只把功能塞进组件。

  4. 具备中小型项目开发的基础工程视角。


第六阶段:常见问题与排错,形成稳定的调试能力

1. 学什么

这一阶段重点学习:

  1. Vue 页面不更新的常见原因

  2. `props` 修改警告排查

  3. `key` 错误导致的列表问题

  4. `reactive` 解构导致响应式丢失

  5. `watch` 死循环

  6. `nextTick` 时机问题

  7. 路由参数变化但页面逻辑未更新

  8. 异步请求竞态

  9. 样式作用域与样式污染

  10. DevTools 和日志调试思路

2. 为什么重要

企业里真正拉开差距的,往往不是"能不能写一个功能",而是:

  • 功能出了问题你能不能快速定位

  • 线上问题你能不能稳定修

  • 你能不能把 bug 归因到状态、模板、生命周期、异步还是工程结构

3. 核心概念

3.1 常见症状与原因对照表

| 症状 | 常见原因 | 第一检查点 |

| --- | --- | --- |

| 数据变了但页面不更新 | 响应式丢失、直接改了非响应式值 | 是否用了 `ref` / `reactive` |

| 列表删除后输入框串位 | `key` 用错 | 是否用了稳定唯一 id |

| 子组件报 `props` 修改警告 | 直接改了父传入值 | 是否应该 `emit` 回父组件 |

| DOM 取不到最新元素 | 更新还没完成 | 是否需要 `nextTick` |

| 搜索结果错乱 | 异步竞态 | 是否取消旧请求或比对请求序号 |

| 页面切路由参数后没刷新 | 组件复用导致逻辑未重新触发 | 是否监听路由参数变化 |

3.2 一个排错主线

  1. 状态有没有变

  2. 变的是不是响应式状态

  3. 模板有没有依赖这个状态

  4. 组件有没有被复用或缓存

  5. 更新时机是不是还没到

  6. 是否被异步请求覆盖

4. 原理解释

4.1 为什么会出现"数据变了页面不变"

最常见不是 Vue 不工作,而是:

  1. 你改的不是响应式数据

  2. 你把 `reactive` 对象错误解构后失去追踪

  3. 模板根本没依赖这个值

4.2 为什么异步请求会造成显示错乱

比如你快速输入搜索词:

  1. 先发请求 A

  2. 再发请求 B

  3. B 先回来

  4. 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 通用排错步骤

  1. 打日志看数据是否变化。

  2. 用 Vue DevTools 看组件状态。

  3. 确认模板是否真的消费了该状态。

  4. 检查 `key`、生命周期、路由参数、缓存组件。

  5. 检查异步请求顺序和覆盖关系。

  6. 最后再怀疑框架或库本身。

6.2 一个真实工程场景

做"用户搜索页"时,输入框快速输入会导致结果闪烁或回退。

解决思路通常是:

  1. 做防抖

  2. 记录最新请求编号

  3. 或取消旧请求

7. 常见误区

  1. **页面没更新就先怀疑 Vue**

  2. **一出 bug 就到处加 `nextTick`**

  3. **日志只看接口返回,不看状态流转**

  4. **不复盘 bug 根因**

  5. **把排错当经验主义**

8. 面试题

  1. Vue 中"数据更新了但页面没更新"可能有哪些原因?

  2. 为什么不推荐解构 `reactive` 对象后直接使用?

  3. 列表为什么不建议用索引做 `key`?

  4. `nextTick` 常见误用有哪些?

  5. 路由参数变化但组件不重新请求数据,你会怎么排查?

9. 自测题

  1. 你能给出一个响应式丢失的例子并修复吗?

  2. 你能描述一个列表错位 bug 的根因吗?

  3. 你能说明为什么某些路由切换后页面没有重新请求吗?

  4. 你能给出一个避免异步竞态的策略吗?

  5. 你能写出自己的 Vue 排错步骤清单吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 独立排查大多数基础到中级 Vue 问题。

  2. 知道 bug 是状态问题、时机问题、通信问题还是异步问题。

  3. 面试中能回答"怎么排错",不只是"怎么用"。


第七阶段:面试与评估,把知识变成可表达、可回答、可证明的能力

1. 学什么

这一阶段重点学习:

  1. Vue 高频面试题分类

  2. 面试回答结构

  3. 概念题、原理题、工程题、排错题的答法

  4. 如何讲自己的 Vue 项目

  5. 如何把"会用"升级成"会解释"

2. 为什么重要

面试不是背书比赛,而是在判断你是否真正理解、是否做过、是否能在团队里承担工作。

面试官尤其关注三点:

  1. 你能否讲清楚因果关系。

  2. 你能否把原理落到代码和项目。

  3. 你是否有稳定的工程判断,而不是只会背八股。

3. 核心概念

3.1 四类问题怎么区分

| 类型 | 面试官想看什么 | 回答重点 |

| --- | --- | --- |

| 概念题 | 你是否知道基础定义 | 先定义,再场景 |

| 原理题 | 你是否理解底层机制 | 先流程,再设计原因 |

| 工程题 | 你是否做过真实项目 | 先场景,再架构与权衡 |

| 排错题 | 你是否能解决问题 | 先定位思路,再给方案 |

3.2 一个通用回答模板

  1. 先给一句定义

  2. 说它解决什么问题

  3. 说核心机制

  4. 说典型场景

  5. 说常见坑或设计权衡

3.3 容易混淆的高频对比

| 对比项 | 关键区别 |

| --- | --- |

| `computed` vs `watch` | 一个算派生值,一个做副作用 |

| `ref` vs `reactive` | 一个包单值,一个代理对象 |

| `v-if` vs `v-show` | 一个控制创建销毁,一个控制显示隐藏 |

| `props` vs Pinia | 一个是近距离通信,一个是共享状态管理 |

| `watch` vs `watchEffect` | 一个显式监听源,一个自动收集依赖 |

4. 原理解释

4.1 为什么面试官喜欢追问"为什么"

因为"怎么用"可以靠记忆,"为什么这样设计"更能体现:

  1. 你是否真正理解

  2. 你是否有迁移能力

  3. 你能否在新场景中做判断

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 项目时,不要只说"我做了登录页和列表页",而要按下面顺序:

  1. 项目是做什么的

  2. 技术栈是什么

  3. 你负责的模块是什么

  4. 页面和状态是怎么组织的

  5. 遇到过什么问题

  6. 你怎么优化或排错的

6.2 一个真实工程场景

比如你做了"后台管理系统",可以这样讲:

  1. 我用 `Vue 3 + Vite + Vue Router + Pinia` 搭建前端项目。

  2. 负责了用户管理、角色权限、订单列表模块。

  3. 页面层和通用组件层做了拆分,接口层做了统一封装。

  4. 对搜索列表做了防抖和请求竞态控制。

  5. 对表单弹窗用 `props / emit` 管理局部状态,全局用户信息放 Pinia。

7. 常见误区

  1. **只背定义,不会讲场景**

  2. **只讲"我做了什么",不讲"为什么这样设计"**

  3. **只讲 happy path,不讲问题和权衡**

  4. **面试题回答过短**

  5. **面试题回答过散**

8. 面试题

  1. Vue 3 和 Vue 2 在响应式实现上有什么差异?

  2. `computed` 和 `watch` 的区别是什么?

  3. `nextTick` 的作用和场景是什么?

  4. 你会如何设计一个 Vue 后台管理项目的结构?

  5. Pinia 和组件局部状态应该怎么划分边界?

9. 自测题

  1. 你能在 3 分钟内解释清楚 Vue 响应式原理吗?

  2. 你能在 2 分钟内解释清楚 `computed` 和 `watch` 的区别吗?

  3. 你能用项目场景说明什么时候要用 Pinia 吗?

  4. 你能讲出一个列表 `key` 用错导致的 bug 吗?

  5. 你能把一个项目经验讲成"场景 -> 设计 -> 问题 -> 解决"的结构吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 系统回答 Vue 基础到中级面试题。

  2. 用原理、场景、权衡三个层次组织答案。

  3. 把项目经验讲得具体、可信、可追问。


第八阶段:学习总结与知识闭环,从会写到持续进阶

1. 学什么

这一阶段的重点不再是新 API,而是:

  1. 如何把 Vue 知识串成体系

  2. 如何通过项目闭环巩固能力

  3. 如何继续进阶到中级甚至更高

  4. 如何建立长期学习方法

2. 为什么重要

很多人学到这里会出现两个问题:

  1. 学了很多点,但串不起来

  2. 会做练习题,但做项目容易散架

3. 核心概念

3.1 Vue 的知识主干

你现在应该把 Vue 理解成下面这棵树:

  1. 最上层是页面与业务需求。

  2. 第二层是组件化和状态管理。

  3. 第三层是响应式、生命周期、通信机制。

  4. 第四层是编译、调度、虚拟 DOM、Diff 等底层原理。

  5. 外围是 Router、Pinia、请求层、构建、测试、部署等工程体系。

3.2 学习本质

Vue 学习不是"背多少 API",而是:

  1. 能不能把页面拆成组件

  2. 能不能把业务拆成状态

  3. 能不能把状态变化映射为界面变化

  4. 能不能把项目组织成可维护工程

  5. 能不能排错和解释

3.3 下一步进阶方向

| 方向 | 为什么值得继续学 |

| --- | --- |

| TypeScript | 企业 Vue 项目中非常常见 |

| Nuxt | SSR、SEO、全栈能力 |

| VueUse | 提高组合式逻辑复用效率 |

| 测试 | 单元测试、组件测试、端到端测试 |

| 性能优化 | 大列表、懒加载、缓存、渲染边界 |

| 源码 | 从会用走向深入理解框架设计 |

4. 原理解释

4.1 为什么项目是最好的复习方式

因为项目会逼你把分散知识点串起来:

  • 模板语法

  • 响应式

  • 路由

  • 状态管理

  • 请求

  • 错误处理

  • 组件复用

  • 排错

4.2 正确的复习路径

  1. 回顾阶段 2 和阶段 3,确保 API 和心智模型稳定。

  2. 回顾阶段 4,确保能解释关键原理。

  3. 用阶段 5 的工程方式做项目。

  4. 用阶段 6 的排错方法复盘问题。

  5. 用阶段 7 的答题方法做口头表达训练。

5. 示例

5.1 一个完整项目闭环示例

建议你做一个"任务管理系统",至少包含:

  1. 登录页

  2. 任务列表页

  3. 任务筛选和搜索

  4. 新增 / 编辑 / 删除任务

  5. 任务状态切换

  6. 路由切换

  7. Pinia 管理用户信息

  8. 接口层封装或本地 mock

6. 工程实践

6.1 推荐的 4 周推进法

  1. 第 1 周:完成阶段 1 到阶段 3 的示例和练习。

  2. 第 2 周:补完阶段 4,开始写小项目。

  3. 第 3 周:按阶段 5 的方式把小项目工程化。

  4. 第 4 周:做排错复盘和模拟面试。

6.2 企业里继续深入会学什么

  1. TypeScript + Vue 3

  2. 权限系统与动态路由

  3. 组件库封装

  4. 大列表性能优化

  5. 单元测试与 E2E 测试

  6. SSR / Nuxt

7. 常见误区

  1. **教程看很多,项目做很少**

  2. **写完项目不复盘**

  3. **只学功能,不学排错**

  4. **只学 Vue,不补 JavaScript 和工程基础**

8. 面试题

  1. 学完 Vue 核心后,你下一步会深入什么,为什么?

  2. 如果让你从零搭一个 Vue 项目,你会按什么顺序做?

  3. 你如何判断自己从初学者进入了初级 / 中级水平?

  4. Vue 项目里你最常见的 bug 类型是什么?你如何建立预防机制?

9. 自测题

  1. 你能把 Vue 的知识主干画出来吗?

  2. 你能给自己设计一个 4 周 Vue 学习计划吗?

  3. 你能用一个项目串起模板、响应式、路由、Pinia、请求封装吗?

  4. 你能清楚说出自己目前最薄弱的是语法、原理、工程还是排错吗?

10. 学完标志

学完这一阶段后,你应该能做到:

  1. 把 Vue 核心知识讲成一个完整体系。

  2. 用项目把知识点串起来,而不是零散记忆。

  3. 明确自己下一步该补什么。

  4. 形成持续迭代、自测、复盘的学习闭环。


评估体系

1. 入门达标标准

达到入门,至少应满足:

  1. 知道 Vue 是什么,能解释"状态驱动 UI"。

  2. 会创建并运行一个 Vue 项目。

  3. 会写 `ref`、事件绑定、条件渲染、列表渲染。

  4. 能完成一个计数器或待办列表。

2. 初级达标标准

达到初级,至少应满足:

  1. 会写组件,能用 `props / emit` 通信。

  2. 能正确使用 `computed`、`watch`、生命周期。

  3. 会使用 Vue Router 和 Pinia 做基础项目。

  4. 能完成一个中小型页面模块。

  5. 能解决常见基础 bug。

3. 中级达标标准

达到中级,至少应满足:

  1. 能解释响应式、调度、虚拟 DOM、Diff 的主链路。

  2. 能按工程方式组织项目目录、接口层、状态层、路由层。

  3. 能处理常见异步竞态、列表 key、响应式丢失、生命周期时机问题。

  4. 能讲清楚项目设计选择和取舍。

  5. 能比较稳定地应对基础到中级 Vue 面试。

4. 一套自测题

  1. Vue 为什么说是"声明式 UI 框架"?

  2. `ref` 和 `reactive` 有什么区别?

  3. `computed` 和 `watch` 的区别是什么?

  4. `v-if` 和 `v-show` 分别适合什么场景?

  5. 为什么 `v-for` 需要 `key`?

  6. 子组件为什么不应该直接修改 `props`?

  7. `onMounted` 和 `onUnmounted` 常用于做什么?

  8. `nextTick` 的作用是什么?

  9. Pinia 适合管理什么状态?

  10. Vue 中"数据变了页面不更新"你会如何排查?

  11. 路由参数变化但页面不更新,你会怎么处理?

  12. Vue 模板最终为什么能变成页面?

5. 一套面试题

  1. Vue 3 响应式原理是怎样的?

  2. `computed` 为什么有缓存?和方法调用有什么区别?

  3. 说说你对 `watch`、`watchEffect` 的理解。

  4. 为什么 Vue 的 DOM 更新通常不是同步立即执行的?

  5. `nextTick` 的底层价值是什么?

  6. 虚拟 DOM 的意义是什么?

  7. `key` 在 Diff 中扮演什么角色?

  8. 你会如何拆分一个复杂页面的组件?

  9. 你会如何设计一个 Vue 后台管理系统?

  10. 什么时候用 `props / emit`,什么时候用 Pinia?

  11. 你在 Vue 项目里遇到过什么典型 bug?如何定位?

  12. Vue 3 相比 Vue 2,你觉得最重要的变化是什么?

6. 一套实战任务

实战任务用于验证"会写页面 + 会组织状态":

  1. 实现一个待办事项应用,支持增删改查、状态筛选、关键字搜索。

  2. 用组件拆分成输入区、列表区、筛选区。

  3. 使用 `computed` 实现筛选结果。

  4. 使用 `watch` 把搜索词同步到本地存储。

  5. 给动态列表使用稳定 `key`。

  6. 页面加入空态提示和删除确认。

7. 一套项目任务

项目名称:任务管理后台系统

最低要求:

  1. 使用 `Vue 3 + Vite + Vue Router + Pinia`。

  2. 包含登录页、任务列表页、任务详情页。

  3. 支持筛选、分页、搜索、新增、编辑、删除。

  4. 有统一 API 层或 mock 数据层。

  5. 有 loading、错误态、空态。

  6. 路由和页面结构清晰。

  7. 能讲清楚状态边界、组件拆分和请求流程。

加分项:

  1. 使用 TypeScript。

  2. 使用 composables 抽分页或请求逻辑。

  3. 处理请求竞态。

  4. 做基础权限控制。

  5. 写一部分测试。

8. 对你回答的评分标准

总分 100,建议按下面维度评分:

| 维度 | 分值 | 评分标准 |

| --- | --- | --- |

| 基础概念 | 20 | 是否能清楚解释核心术语 |

| 代码能力 | 25 | 是否能独立写出常用页面和组件 |

| 原理理解 | 20 | 是否能解释响应式、更新、Diff 等主链路 |

| 工程实践 | 15 | 是否会用 Router、Pinia、API 分层 |

| 排错能力 | 10 | 是否有清晰定位步骤 |

| 面试表达 | 10 | 是否能讲清楚定义、场景、原理、权衡 |

参考分段:

  1. 0 到 59:知识零散,项目和面试都不稳定。

  2. 60 到 74:达到入门,可写简单页面。

  3. 75 到 84:达到初级,可做中小模块。

  4. 85 到 100:接近中级,具备解释、工程、排错综合能力。

9. 如何根据错误结果反向补课

| 你错在哪类题 | 说明短板在哪 | 回补阶段 |

| --- | --- | --- |

| 模板语法、组件基础题 | 页面表达能力不足 | 第二阶段 |

| `ref`、`reactive`、`computed`、生命周期题 | 状态和机制没吃透 | 第三阶段 |

| 响应式原理、`nextTick`、`key`、Diff 题 | 原理理解不足 | 第四阶段 |

| Router、Pinia、目录结构、API 分层题 | 工程化能力不足 | 第五阶段 |

| 页面不更新、竞态、路由复用题 | 排错能力不足 | 第六阶段 |

| 项目讲不清、答案发散 | 面试表达不足 | 第七阶段 |

进一步的补课方法:

  1. 概念不会:回到对应阶段,重写定义并举一个自己的例子。

  2. 代码不会:重写该阶段最小示例,要求不看资料完成。

  3. 原理不会:把运行流程画成步骤图,再口头讲一遍。

  4. 工程不会:按第五阶段重新搭一个最小项目骨架。

  5. 排错不会:故意制造一个 bug,再按第六阶段流程定位。

  6. 面试不会:录音回答高频题,听自己是否只会背定义。

10. 最终闭环执行方案

建议你按下面方式执行这份文档:

  1. 完成第一到第三阶段,建立 Vue 核心使用能力。

  2. 完成第四阶段,把 API 背后的原理串起来。

  3. 完成第五阶段,用工程方式做一个项目骨架。

  4. 完成第六阶段,主动制造并修复几个典型 bug。

  5. 完成第七阶段,做一次模拟面试。

  6. 完成第八阶段,交付一个完整项目并复盘。

到这里,你对 Vue 的掌握就不再是"看过教程",而是更接近:

  • 能理解

  • 能解释

  • 能上手

  • 能排错

  • 能通过基础到中级面试

相关推荐
苏瞳儿2 小时前
前端/后端-配置跨域
前端·javascript·node.js·vue
曲幽4 小时前
告别手写 API 胶水代码:FastAPI 与 Vue 的“契约自动机” OpenAPI 实战
python·typescript·vue·fastapi·web·swagger·openapi·codegen
桂森滨21 小时前
Vue3+Pinia+Vite+TS 还原高性能外卖APP项目 4️⃣首页开发
前端·typescript·vue
天下无贼!2 天前
【功能实现】基于Vue3+TS实现大文件分片上传
开发语言·javascript·node.js·vue·html5
曲幽2 天前
FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南”
python·vue·fastapi·web·vite·proxy·cors·env
落魄江湖行2 天前
入门篇四:Nuxt4布局系统:让页面框架复用变得简单
前端·vue·nuxt4
色空大师2 天前
网站搭建实操(十)前端搭建
前端·webpack·vue·网站·论坛
.生产的驴4 天前
Vue3 超大字体font-slice按需分片加载,极速提升首屏速度, 中文分片加载方案,性能优化
前端·vue.js·windows·青少年编程·性能优化·vue·rescript