Vue 基础学习笔记
适合目标:系统掌握 Vue 3 的基础开发能力,并能回答常见 Vue 面试题。
学习定位:这一份偏“会用、会写、会答”,主线以 Vue 3 和 Composition API 为核心。
学习原则:先理解 Vue 的响应式和模板思维,再记 API;先会写组件,再讲优化;先把高频场景跑通,再做面试表达。
目录
- 学习总览
- Vue 的核心思维
- 模板语法与指令
- 组件基础
- 响应式基础
- Composition API 核心
- 生命周期与副作用处理
- 组件通信
- 表单、插槽与内置组件
- Vue Router 与状态管理
- 性能优化手段
- Vue 3 高频知识点
- 高频面试题
- 6 小时学习规划
- 一页速记总结
- 背诵口诀
1. 学习总览
1.1 Vue 到底在解决什么问题
Vue 本质上是在解决前端页面开发里的几个核心问题:
- 页面如何拆成可复用组件
- 数据变化后,视图如何自动更新
- 模板和逻辑如何更自然地组织
- 项目变大后,状态、路由、组件协作如何维护
你可以把 Vue 理解成:
界面 = 状态的声明式映射
这意味着:
- 你更关注“数据是什么”
- 你更关注“模板该怎么描述界面”
- 你不需要频繁手动操作 DOM
1.2 Vue 学习的三条主线
主线 1:声明式模板
通过模板和指令表达界面,而不是自己逐步操作 DOM。
主线 2:响应式系统
数据变了,依赖它的视图和计算会自动更新。
主线 3:组件化
把页面拆成独立、可复用、可组合的组件。
1.3 Vue 学习顺序
建议按这个顺序掌握:
- 模板语法和常用指令
- 组件、props、emit
ref、reactive、computed、watch- 生命周期
setup与 Composition API- 插槽、
provide/inject、v-model - Router、Pinia
- Vue 3 优化和面试题
1.4 本笔记的版本主线
这份笔记默认以 Vue 3 为主线,重点使用:
- Composition API
<script setup>- Vue Router 4
- Pinia
2. Vue 的核心思维
2.1 声明式 UI
Vue 和 React 一样,都是声明式 UI 框架。
意思是:
- 你描述“什么状态对应什么界面”
- 框架帮你把状态变化同步到视图
例如:
<template>
<div>
<p>当前计数:{{ count }}</p>
<button @click="count++">+1</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
2.2 Vue 的优势思维
Vue 的上手体验通常更顺,是因为它在模板层做了很多友好设计:
- 模板更接近 HTML
- 指令语法统一
- 单文件组件组织方式清晰
- Composition API 可以灵活抽逻辑
2.3 数据驱动视图
Vue 最重要的体验就是:
改数据,不改 DOM
示例:
<template>
<h1>{{ title }}</h1>
</template>
<script setup>
import { ref } from 'vue'
const title = ref('Hello Vue')
</script>
当 title.value 变化时,界面会自动更新。
2.4 组件化思维
Vue 里一个页面通常会拆成:
- 页面级组件
- 业务组件
- 通用组件
- 布局组件
- 表单组件
拆分标准仍然是:
- 是否可复用
- 是否职责独立
- 是否会单独变化
2.5 Options API 和 Composition API
Vue 3 仍支持 Options API,但 Composition API 是主流重点。
Options API
按配置项组织代码:
datamethodscomputedwatch- 生命周期
Composition API
按“逻辑功能”组织代码,适合复杂组件逻辑复用。
2.6 记忆口诀
Vue 用模板描述界面,用响应式驱动更新,用组件组织页面。
3. 模板语法与指令
3.1 插值语法
最常见的是双大括号:
<template>
<p>{{ message }}</p>
</template>
适合输出文本。
3.2 常见指令总览
Vue 模板里最常见的指令:
v-bindv-onv-ifv-showv-forv-modelv-slot
3.3 v-bind
用于绑定属性。
<img v-bind:src="imageUrl" />
简写:
<img :src="imageUrl" />
3.4 v-on
用于绑定事件。
<button v-on:click="handleClick">点击</button>
简写:
<button @click="handleClick">点击</button>
3.5 v-if 和 v-show
v-if
控制是否渲染节点。
<p v-if="visible">显示内容</p>
特点:
- 条件为假时,节点不渲染
- 切换成本较高
- 初始不渲染时更省
v-show
通过 CSS display 控制显示隐藏。
<p v-show="visible">显示内容</p>
特点:
- 节点一直存在
- 频繁切换更合适
面试怎么答
v-if是真正的条件渲染v-show是控制显示隐藏- 频繁切换用
v-show - 初始条件不一定成立时可优先考虑
v-if
3.6 v-for
用于列表渲染。
<li v-for="item in list" :key="item.id">
{{ item.name }}
</li>
和 React 一样,也要重视 key。
3.7 为什么 v-for 需要 key
key 用来帮助 Vue 在 Diff 时识别节点身份。
作用:
- 提高更新准确性
- 避免错误复用
- 保持局部状态稳定
3.8 v-if 和 v-for 不建议写在同一个元素上
因为:
- 优先级和执行语义容易引起混乱
- 可读性差
- 不利于维护
更好的方式:
- 先通过计算属性过滤数据
- 再循环渲染
3.9 事件修饰符
Vue 提供了很多事件修饰符,能减少样板代码。
常见:
.stop.prevent.once.enter
<form @submit.prevent="handleSubmit"></form>
3.10 样式和 class 绑定
<div :class="{ active: isActive }"></div>
<div :style="{ color: textColor }"></div>
3.11 模板指令记忆口诀
冒号绑属性,@ 绑事件,if 控渲染,show 控显示,for 渲列表,model 管双向。
4. 组件基础
4.1 单文件组件 SFC
Vue 常见组件格式是单文件组件:
<template>
<div>Hello Vue</div>
</template>
<script setup>
</script>
<style scoped>
</style>
优点:
- 模板、逻辑、样式集中
- 更适合组件化开发
- 易于维护
4.2 props
父组件向子组件传值使用 props。
<script setup>
defineProps({
title: String,
count: Number
})
</script>
使用:
<Child title="标题" :count="1" />
4.3 props 为什么不能直接修改
因为:
- props 是父组件传下来的
- 单向数据流要求子组件不要直接改父传数据
- 直接修改会让数据来源混乱
如果需要基于 props 做可变值,通常:
- 拷贝一份本地状态
- 或通过事件通知父组件修改
4.4 emits
子组件向父组件通信常用事件派发。
<script setup>
const emit = defineEmits(['update'])
function handleClick() {
emit('update', 123)
}
</script>
父组件:
<Child @update="handleUpdate" />
4.5 单向数据流
Vue 的通信主线是:
- 父组件通过
props向下传 - 子组件通过
emit向上通知
这和 React 的 props + callback 思想很接近。
4.6 script setup
<script setup> 是 Vue 3 中非常重要的书写方式。
优点:
- 更简洁
- 模板能直接使用脚本中的变量
- 更适合 Composition API
4.7 defineProps 和 defineEmits
它们是 <script setup> 中的编译宏。
<script setup>
const props = defineProps({
title: String
})
const emit = defineEmits(['change'])
</script>
4.8 组件注册
Vue 3 + SFC 中,导入组件后通常可以直接在模板中使用。
<script setup>
import UserCard from './UserCard.vue'
</script>
<template>
<UserCard />
</template>
4.9 记忆口诀
props 往下传,emit 往上抛,setup 里写逻辑,模板里直接用。
5. 响应式基础
Vue 最核心的底层能力就是响应式。基础学习里先会用,源码学习里再深挖原理。
5.1 什么是响应式
响应式可以理解成:
当数据变化时,依赖它的地方自动感知并更新
在 Vue 中,模板、计算属性、侦听器都能基于响应式数据自动工作。
5.2 ref
ref 用于包装基本类型,也可以包装对象。
<script setup>
import { ref } from 'vue'
const count = ref(0)
function add() {
count.value++
}
</script>
特点:
- JS 中访问用
.value - 模板中会自动解包
5.3 reactive
reactive 用于创建对象类型的响应式代理。
<script setup>
import { reactive } from 'vue'
const user = reactive({
name: 'Tom',
age: 18
})
</script>
5.4 ref 和 reactive 怎么选
记忆建议:
- 基本类型优先
ref - 对象类型常用
reactive - 实际项目中很多团队会“默认优先
ref”,因为组合和传递更稳定
5.5 computed
计算属性用于基于已有响应式数据派生新值。
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('Tom')
const lastName = ref('Jerry')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
</script>
特点:
- 有缓存
- 依赖不变时不会重复计算
- 更适合描述派生状态
5.6 methods 和 computed 区别
computed
- 基于依赖缓存
- 更适合派生值
methods
- 每次调用都会执行
- 更适合普通动作和逻辑
5.7 watch
用于监听某个响应式数据变化,并执行副作用逻辑。
<script setup>
import { ref, watch } from 'vue'
const keyword = ref('')
watch(keyword, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
</script>
适合:
- 请求数据
- 监听路由变化
- 数据变化后的副作用处理
5.8 watchEffect
watchEffect 会自动收集内部用到的响应式依赖。
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
watchEffect(() => {
console.log('count:', count.value)
})
</script>
5.9 watch 和 watchEffect 区别
watch更明确,指定监听源watchEffect更自动,执行时收集依赖watch更适合精确控制watchEffect更适合快速响应式副作用
5.10 响应式基础口诀
ref 管值,reactive 管对象,computed 管派生,watch 管副作用监听。
6. Composition API 核心
6.1 setup 是什么
setup 是 Composition API 的入口。
在 <script setup> 模式下,你通常不需要手写 setup(),但本质仍然是:
- 在组件创建阶段执行
- 用于声明响应式状态和逻辑
- 模板会使用这里暴露的内容
6.2 为什么 Composition API 更适合复杂逻辑
因为它按“功能逻辑”组织代码,而不是按配置项分散组织。
例如一个搜索组件可能会有:
- 搜索词逻辑
- 请求逻辑
- 分页逻辑
- 表单验证逻辑
用 Composition API 可以按功能拆分成 composables。
6.3 什么是 Composable
Composable 就是可复用的组合式函数。
例如:
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
const update = (event: MouseEvent) => {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
6.4 toRef 和 toRefs
当你从响应式对象中解构属性时,可能会丢失响应式关联,所以常用:
toReftoRefs
import { reactive, toRefs } from 'vue'
const state = reactive({
name: 'Tom',
age: 18
})
const { name, age } = toRefs(state)
6.5 readonly
用于创建只读响应式对象,适合保护数据不被直接修改。
6.6 shallowRef 和 shallowReactive
浅层响应式,只跟踪第一层。
适合:
- 大对象
- 第三方实例
- 不希望深度递归代理的数据
6.7 nextTick
Vue 更新 DOM 是异步批量进行的,nextTick 用来等待 DOM 更新完成后再执行某些逻辑。
import { nextTick } from 'vue'
await nextTick()
适合:
- 读更新后的 DOM
- 等待列表渲染完成
- 聚焦输入框
6.8 provide / inject
用于跨层级通信。
<script setup>
import { provide, inject } from 'vue'
provide('theme', 'dark')
const theme = inject('theme', 'light')
</script>
适合:
- 祖孙组件共享数据
- 插件能力
- 表单容器上下文
6.9 Composition API 口诀
setup 是入口,composable 做复用,toRefs 防解构丢响应,nextTick 等 DOM 更新。
7. 生命周期与副作用处理
7.1 Vue 组件生命周期
Composition API 中常见生命周期:
onBeforeMountonMountedonBeforeUpdateonUpdatedonBeforeUnmountonUnmounted
7.2 onMounted
常用于:
- 首次请求数据
- 获取 DOM
- 初始化第三方库
7.3 onUnmounted
常用于清理:
- 定时器
- 事件监听
- 订阅
- 第三方实例
7.4 生命周期与 watch 的区别
- 生命周期关注组件阶段
watch关注响应式数据变化
7.5 什么时候用 computed,什么时候用 watch
computed
- 用于派生值
- 应该尽量是纯计算
watch
- 用于副作用
- 用于异步请求
- 用于监听并触发外部动作
记忆原则:
能算出来,用 computed;需要做事,用 watch。
7.6 记忆口诀
mounted 做初始化,unmounted 做清理;computed 算结果,watch 做副作用。
8. 组件通信
8.1 父传子
使用 props。
8.2 子传父
使用 emit。
8.3 兄弟组件通信
通过共同父组件中转,或者提升状态。
8.4 跨层级通信
可以用:
provide/inject- 状态管理库
- 路由状态
8.5 v-model 本质是什么
v-model 本质上是:
- 一个 prop
- 加上一个对应的更新事件
在 Vue 3 中,组件上的 v-model 默认对应:
modelValueupdate:modelValue
示例:
<script setup>
const props = defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
function handleInput(event) {
emit('update:modelValue', event.target.value)
}
</script>
<template>
<input :value="modelValue" @input="handleInput" />
</template>
8.6 多个 v-model
Vue 3 支持多个 v-model,适合复杂表单组件。
8.7 插槽 slots
插槽用于让父组件向子组件传递“模板内容”。
默认插槽
<Card>
<p>内容</p>
</Card>
具名插槽
<template #header>
<h1>标题</h1>
</template>
作用域插槽
子组件把数据暴露给父组件的插槽内容使用。
8.8 记忆口诀
props 往下,emit 往上,provide/inject 跨层,slot 传结构,v-model 管双向绑定约定。
9. 表单、插槽与内置组件
9.1 表单双向绑定
Vue 的表单体验通常更顺,因为有 v-model。
<input v-model="keyword" />
9.2 表单修饰符
常见:
.trim.number.lazy
9.3 KeepAlive
用于缓存动态组件实例,避免切换时重复销毁和重建。
适合:
- tab 页
- 路由页面缓存
- 表单暂存
9.4 Teleport
允许把组件的一部分模板渲染到组件树外的其他 DOM 位置。
适合:
- 弹窗
- 全局提示
- Drawer
9.5 Suspense
用于协调异步依赖加载时的等待态。
9.6 Transition
用于为元素或组件进入离开添加过渡动画。
9.7 这些内置组件为什么常考
因为它们体现了 Vue 对实际 UI 组织的支持:
KeepAlive关注缓存Teleport关注挂载位置Suspense关注等待态Transition关注交互体验
10. Vue Router 与状态管理
10.1 Vue Router 是什么
Vue Router 是 Vue 官方路由方案。
常见职责:
- URL 和页面映射
- 嵌套路由
- 动态路由
- 导航守卫
10.2 常见路由模式
createWebHistorycreateWebHashHistory
10.3 导航守卫
常见用法:
- 登录校验
- 权限拦截
- 页面切换前确认
10.4 状态管理为什么需要 Pinia
当共享状态越来越多时,只靠 props、emit、provide/inject 会变复杂。
Pinia 的优势:
- API 简洁
- 更贴合 Vue 3
- 类型支持更自然
- 比 Vuex 更轻量、更现代
10.5 Pinia 核心概念
- Store
- State
- Getter
- Action
10.6 状态管理选型建议
- 小项目:
ref/reactive + provide/inject - 中大型项目:Pinia
10.7 一句话记忆
路由管页面切换,Pinia 管共享状态。
11. 性能优化手段
11.1 Vue 性能优化总原则
不要一上来就做细碎优化,先看问题来源:
- 是不是组件拆分不合理
- 是不是渲染范围过大
- 是不是依赖追踪太广
- 是不是列表过大
11.2 合理拆分组件
让状态变化尽量局部化。
11.3 computed 优于模板里复杂表达式
把复杂派生逻辑放进 computed,既清晰又有缓存。
11.4 watch 不要滥用
很多场景其实应该用:
computed- 直接函数调用
- 业务逻辑拆分
11.5 v-if 和 v-show 选对场景
频繁切换:
- 优先考虑
v-show
初始不一定渲染:
- 优先考虑
v-if
11.6 大列表优化
- 稳定
key - 分页
- 虚拟列表
- 避免每项里做重计算
11.7 路由与组件懒加载
通过动态导入降低首屏体积。
11.8 shallow 系列 API
用于避免深层响应式代理带来的不必要成本。
11.9 KeepAlive 合理使用
对需要缓存的页面和组件使用,不要全局无脑缓存。
11.10 性能优化答题模板
- 合理拆分组件,控制更新范围
- 优先用
computed处理派生值 - 避免无意义
watch - 大列表结合稳定 key、分页和虚拟列表
- 使用路由懒加载、异步组件、
KeepAlive
12. Vue 3 高频知识点
12.1 Vue 3 和 Vue 2 的核心变化
常见答法:
- 响应式从
Object.defineProperty转向Proxy - 更好的 TypeScript 支持
- 引入 Composition API
- 更细粒度的编译优化
- 内置能力如 Teleport、Suspense 等增强
12.2 Composition API 为什么更受欢迎
- 更适合逻辑复用
- 更适合复杂组件
- TypeScript 体验更好
- 代码组织更灵活
12.3 script setup 有什么好处
- 更少样板代码
- 更自然暴露给模板
- 编译层面更高效
12.4 ref 和 reactive 区别
ref更适合基本类型,也能包对象reactive更适合对象代理ref访问依赖.value- 模板里会自动解包
12.5 computed 和 watch 区别
computed是派生值,强调结果watch是副作用监听,强调动作
12.6 nextTick 是什么
Vue 更新 DOM 是异步批量执行的,nextTick 用于等待这轮 DOM 更新完成。
12.7 v-model 在组件上是怎么实现的
Vue 3 中默认是:
modelValueupdate:modelValue
12.8 记忆口诀
Vue 3 核心升级看三件事:Proxy、Composition API、编译优化。
13. 高频面试题
13.1 Vue 的响应式原理怎么简答
答:
- Vue 会把数据变成响应式对象
- 在读取时收集依赖
- 在修改时触发依赖更新
- Vue 3 主要基于
Proxy
13.2 ref 和 reactive 的区别
答:
ref适合基本类型,也可包装对象reactive更适合对象ref通过.value访问- 模板里会自动解包
13.3 computed 和 watch 区别
答:
computed更适合根据已有状态计算新值watch更适合监听变化后执行副作用computed有缓存
13.4 v-if 和 v-show 区别
答:
v-if控制是否渲染v-show控制显示隐藏- 频繁切换用
v-show - 初始不一定渲染可优先
v-if
13.5 Vue 3 为什么用 Proxy
答:
- 能更完整拦截对象操作
- 对数组、对象新增删除等场景支持更自然
- 相比
Object.defineProperty更灵活
13.6 nextTick 为什么存在
答:
因为 Vue 会把更新合并后异步刷新 DOM,nextTick 让你在 DOM 更新完成后执行逻辑。
13.7 provide/inject 和 Pinia 怎么选
答:
- 简单跨层共享可用
provide/inject - 复杂全局共享状态更适合 Pinia
13.8 script setup 为什么常用
答:
更简洁、样板更少、逻辑暴露更自然,也更适合 Composition API。
13.9 面试回答模板
- 先说定义
- 再说原理
- 再说场景
- 最后说注意点
14. 6 小时学习规划
第 1 小时:Vue 核心心法
目标:
- 搞懂声明式模板
- 搞懂响应式
- 搞懂组件化
必须掌握:
templatepropsref/reactive
第 2 小时:模板和指令
目标:
- 掌握
v-bind、v-on - 掌握
v-if、v-show、v-for - 掌握
v-model
第 3-4 小时:Composition API
目标:
- 吃透
ref、reactive - 掌握
computed、watch - 掌握生命周期和 composables
必须掌握:
computed和watch区别nextTickprovide/inject
第 5 小时:组件通信 + 工程常用能力
目标:
- 掌握
props/emit - 掌握 slots
- 了解 Router 和 Pinia
- 理解内置组件
KeepAlive/Teleport
第 6 小时:复盘 + 面试表达
建议:
- 自己写一个表单组件
- 自己写一个
v-model组件 - 自己写一个
useFetch风格 composable - 自己讲清
ref/reactive/computed/watch
15. 一页速记总结
15.1 Vue 主线
- 模板驱动 UI
- 响应式驱动更新
- 组件化组织页面
15.2 基础 API
refreactivecomputedwatchonMounted
15.3 通信
propsemitprovide/injectslotv-model
15.4 工程能力
- Vue Router
- Pinia
nextTickKeepAliveTeleport
15.5 优化
- 合理拆组件
- 善用
computed - 稳定 key
- 异步组件与懒加载
- 大列表优化
16. 背诵口诀
16.1 Vue 基础口诀
模板描述界面,响应式驱动更新,组件负责组合,数据变化自动刷新。
16.2 Composition API 口诀
ref 管值,reactive 管对象,computed 算派生,watch 做副作用。
16.3 组件通信口诀
props 往下传,emit 往上抛,inject 跨层拿,slot 传结构,v-model 是约定。
16.4 优化口诀
先拆组件,再控范围;先看依赖,再做缓存。
17. 最后给你的建议
想快速学会 Vue,建议你按这个练习顺序走:
- 先手敲 3 个小组件:计数器、Todo、表单
- 再手敲 3 个响应式场景:
computed、watch、nextTick - 再手敲 2 个通信场景:
props/emit、v-model - 最后做一个带路由和 Pinia 的小项目
真正学会的标准不是“看懂”,而是:
- 你能自己写组件
- 你能自己拆响应式状态
- 你能解释
computed和watch - 你能说出 Vue 3 的核心升级点
把这些打通后,Vue 使用层就会非常稳。