📘 Vue 3 考试速通指南
—— 每一行代码的作用都讲清楚,专治“背了但不会用”
第二章:数据绑定与响应式系统
1. 文本插值 {{ }}
<template>
<p>Hello, {{ name }}!</p>
</template>
- 作用:在 HTML 元素的文本内容中动态插入 JavaScript 表达式的计算结果。
- 原理:Vue 在编译模板时,会将
{{ name }}替换为一个对响应式数据name的读取操作。当name变化时,DOM 自动更新。 - 限制:只能用于标签内部的文本节点,不能用于属性(如
<div id="{{ name }}">是错误的)。
2. HTML 绑定 v-html
<template>
<div v-html="htmlContent"></div>
</template>
-
作用:将字符串作为原始 HTML 渲染到页面上。
-
注意:
htmlContent必须是字符串,例如:'<strong>加粗文字</strong>'- 不安全:如果内容来自用户输入,可能引发 XSS 攻击。
-
对比文本插值:
{{ }}会转义 HTML 标签(显示为纯文本),而v-html不会。
3. 属性绑定 v-bind(简写 :)
<img :src="imageUrl" :alt="imageAlt" :class="{ active: isActive }" />
-
作用:动态绑定 HTML 元素的属性值。
-
逐项解释:
:src="imageUrl"→ 将src属性设为imageUrl变量的值(响应式)。:alt="imageAlt"→ 同理,绑定alt属性。:class="{ active: isActive }"→ 动态绑定 CSS 类:当isActive为true时,添加active类。
-
为什么需要? 因为 HTML 属性默认是静态字符串,无法直接写变量。
v-bind让属性“活”起来。
4. 双向数据绑定 v-model
<input v-model="message" />
- 作用:在表单元素(如 input、textarea、select)上创建双向绑定——数据变化更新视图,用户输入也更新数据。
- 等价写法(理解原理) :
<input
:value="message"
@input="message = $event.target.value"
/>
-
逐句解释:
:value="message":将 input 的值设为message(数据 → 视图)@input="...":监听 input 事件,把用户输入的新值赋给message(视图 → 数据)
-
适用元素:
<input type="text">、<textarea>:绑定value<input type="checkbox">:绑定checked<select>:绑定选中的value
✅ 考试重点:
v-model是语法糖,本质是v-bind:value + v-on:input的组合。
5. 响应式数据:ref 与 reactive
(1)ref
import { ref } from 'vue'
const count = ref(0)
-
作用:创建一个响应式的引用对象,适用于基本类型(number、string)或对象。
-
特点:
- 在
<script setup>中访问/修改需用.value:count.value++ - 在模板中自动解包(无需
.value):{{ count }}
- 在
-
底层结构:
count实际是一个对象{ value: 0 },Vue 通过.value追踪依赖。
(2)reactive
import { reactive } from 'vue'
const user = reactive({ name: 'Alice', age: 20 })
-
作用:基于 ES6 Proxy 创建一个响应式的对象。
-
特点:
- 直接访问属性:
user.name = 'Bob' - 不能用于基本类型(如
reactive(0)无效) - 无法自动解包(但模板中可直接用属性)
- 直接访问属性:
🔍 区别总结:
| 对比项 | ref | reactive |
|---|---|---|
| 适用类型 | 基本类型、对象 | 仅对象/数组 |
| 访问方式(script) | .value | 直接属性 |
| 模板中使用 | 自动解包 | 直接使用 |
| 是否可替换整个对象 | 是(obj = ref(newObj)) | 否(替换后失去响应性) |
✅ 简答题高频答案:推荐用
ref管理简单状态,reactive管理复杂对象。
🧪 示例代码(Vue 3 + Composition API)
import { ref, reactive } from 'vue'
// 使用 ref
const count = ref(0)
const user = ref({ name: 'Alice' })
// 使用 reactive
const state = reactive({
count: 0,
user: { name: 'Bob' }
})
在 <script setup> 中操作:
// ref 需要 .value
count.value++ // ✅ 正确
user.value.name = 'Charlie' // ✅ 修改对象属性
// 替换整个 ref 对象 ✅ 依然响应式
user.value = { name: 'David' }
// reactive 直接操作属性
state.count++
state.user.name = 'Eve'
// ❌ 错误!这样会丢失响应性:
// state = { count: 10, user: { name: 'New' } } // 不允许!
在模板中使用(两者写法一样):
<template>
<p>Ref count: {{ count }}</p>
<p>Ref user: {{ user.name }}</p>
<p>Reactive count: {{ state.count }}</p>
<p>Reactive user: {{ state.user.name }}</p>
</template>
💡 模板中 Vue 会自动“解包”
ref,所以你不需要写count.value。
6. 计算属性 computed vs 侦听器 watch
(1)计算属性
import { computed, ref } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`
})
- 作用:定义一个依赖其他响应式数据的派生值,具有缓存性。
- 缓存机制:只要
firstName或lastName没变,多次访问fullName不会重新计算。 - 适用场景:格式化显示、过滤列表、拼接字符串等。
(2)侦听器
import { watch } from 'vue'
watch(count, (newVal, oldVal) => {
console.log(`计数从 ${oldVal} 变为 ${newVal}`)
})
-
作用:监听某个响应式数据的变化,并在变化时执行副作用(如发请求、打日志)。
-
与 computed 区别:
computed返回值,用于模板展示;watch执行操作,用于逻辑处理。
-
高级用法:可监听多个数据、深度监听对象(
{ deep: true })、立即执行({ immediate: true })
第三章:条件渲染、列表与事件
1. v-if 与 v-show
<div v-if="isLoggedIn">欢迎回来!</div>
<div v-show="showTips">提示信息</div>
-
v-if:- 作用:根据表达式真假创建或销毁 DOM 元素。
- 性能:切换开销大(涉及组件生命周期),但初始渲染快。
- 适用:条件很少改变的场景(如权限判断)。
-
v-show:- 作用:始终渲染 DOM,通过
display: none控制显隐。 - 性能:初始渲染慢(DOM 已存在),但切换快。
- 适用:频繁切换的场景(如 tab 切换)。
- 作用:始终渲染 DOM,通过
❗ 注意:
v-if和v-for不要同时用在同一元素上(官方不推荐)。
2. v-for 列表渲染
<li v-for="(item, index) in items" :key="item.id">
{{ index }}: {{ item.name }}
</li>
-
作用:基于数组或对象循环生成多个元素。
-
参数说明:
item:当前遍历的元素index:当前索引(可选)items:响应式数组
-
:key的作用:- 帮助 Vue 识别每个节点的唯一身份,优化虚拟 DOM diff 算法。
- 必须是唯一且稳定的值(如数据库 ID),不要用
index作为 key(除非列表不可变) 。
3. 事件处理 v-on(简写 @)
<button @click="handleClick">点击</button>
<button @click="handleClick(item)">传参</button>
<form @submit.prevent="onSubmit">提交</form>
-
@click="handleClick":- 监听 click 事件,触发
handleClick函数。
- 监听 click 事件,触发
-
@click="handleClick(item)":- 内联处理器,可传递参数(此时
$event需手动传入)。
- 内联处理器,可传递参数(此时
-
修饰符
.prevent:- 阻止表单默认提交行为(等价于
event.preventDefault())。
- 阻止表单默认提交行为(等价于
-
常用修饰符:
.stop:阻止事件冒泡.once:只触发一次.enter:仅回车键触发(可用于 input)
第四章:组件通信与插槽
1. 父 → 子:props
<!-- 父组件 -->
<ChildComp :title="pageTitle" />
<!-- 子组件 -->
<script setup>
const props = defineProps({
title: { type: String, required: true }
})
</script>
<template>
<h1>{{ props.title }}</h1>
</template>
- 作用:父组件向子组件传递数据。
defineProps:声明接收的 props 类型和规则。- 单向数据流:子组件不能直接修改
props(否则报错),如需修改应 emit 事件通知父组件。
2. 子 → 父:emit
<!-- 子组件 -->
<script setup>
const emit = defineEmits(['update-name'])
function changeName() {
emit('update-name', 'New Name')
}
</script>
<!-- 父组件 -->
<ChildComp @update-name="handleNameUpdate" />
defineEmits:声明组件会触发哪些自定义事件。emit('事件名', 数据):触发事件并传递数据。- 父组件用
@事件名监听,执行回调函数。
3. 跨级通信:provide / inject
// 祖先组件
import { provide, ref } from 'vue'
const theme = ref('dark')
provide('theme', theme) // 提供响应式数据
// 后代组件
import { inject } from 'vue'
const theme = inject('theme') // 注入数据
- 作用:跳过中间组件,实现祖先 ↔ 后代的数据传递。
- 响应式:若提供的是
ref或reactive,则注入方也能响应变化。 - 适用场景:全局配置(如主题、语言)。
4. 插槽(Slot)
| 没插槽 | 有插槽 |
|---|---|
| 子组件内容写死,无法定制 | 父组件可以“往子组件里塞任意内容” |
| 复用性差 | 一个子组件,N 种用法 |
| 父子紧耦合 | 父子松耦合,各司其职 |
插槽就是“在子组件里留个坑,让父组件来填内容”。
(1)默认插槽
<!-- 子组件 -->
<slot>默认内容</slot>
<!-- 父组件 -->
<Child>自定义内容</Child>
- 作用:父组件向子组件插入任意内容。
- 若父组件没传内容,则显示“默认内容”。
(2)具名插槽
<!-- 子组件 -->
<header><slot name="header"></slot></header>
<footer><slot name="footer"></slot></footer>
<!-- 父组件 -->
<Child>
<template #header>这是头部</template>
<template #footer>这是底部</template>
</Child>
#header是v-slot:header的简写- 用于在子组件不同位置插入不同内容。
(3)作用域插槽(子传数据给父)
<!-- 子组件 -->
<slot :user="user" :logout="handleLogout"></slot>
<!-- 父组件 -->
<Child v-slot="{ user, logout }">
<button @click="logout">退出 {{ user.name }}</button>
</Child>
- 关键点:子组件通过 slot 传递数据(
user,logout)给父组件。 - 父组件用
v-slot="{ ... }"解构接收。 - 用途:封装可复用组件(如表格、弹窗),让父组件决定如何渲染子组件的数据。
第六章:Vue Router(编程题核心!)
1. 创建路由实例
// router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue') // 懒加载
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
},
{
path: '/old-path',
redirect: '/' // 重定向到首页
}
]
const router = createRouter({
history: createWebHashHistory(), // 使用 hash 模式(#)
routes
})
export default router
createRouter:创建路由器实例。createWebHashHistory():使用 URL 的 hash 模式(兼容性好,无需服务器配置)。routes:路由配置数组,每项包含path、component、可选name。redirect:当访问/old-path时,自动跳转到/。
2. 路由视图与导航
<!-- App.vue -->
<template>
<!-- 声明式导航 -->
<router-link to="/">首页</router-link>
<router-link :to="{ name: 'About' }">关于</router-link>
<!-- 路由出口 -->
<router-view />
</template>
-
<router-link>:- 渲染为
<a>标签,点击时不刷新页面,仅切换组件。 to="/":字符串路径:to="{ name: 'About' }":使用命名路由(推荐,解耦路径)
- 渲染为
-
<router-view>:- 占位符,匹配的路由组件会在这里渲染。
3. 编程式导航(重点!)
// 在 setup() 或方法中
import { useRouter } from 'vue-router'
const router = useRouter()
// 跳转到首页
router.push('/')
// 使用命名路由跳转
router.push({ name: 'About' })
// 携带查询参数(URL 显示 ?id=123)
router.push({ path: '/user', query: { id: 123 } })
// 路由参数(需在路由中定义 /user/:id)
router.push({ name: 'User', params: { id: 123 } })
// 替换当前历史记录(不能后退)
router.replace('/login')
// 后退一页
router.go(-1)
✅ 编程题模板:通常要求“点击按钮跳转并传参”,务必掌握
push+query/params。
📝 总结:按题型复习建议
| 题型 | 复习重点 | 示例问题 |
|---|---|---|
| 简答题(40分) | 概念辨析、原理说明 | “ref 和 reactive 有什么区别?”、“v-model 的原理是什么?” |
| 程序填空(35分) | 语法细节、指令写法 | 补全 emit 语句、写出 v-for 的 key、填写插槽语法 |
| 编程题(25分) | 路由配置 + 跳转逻辑 | 创建路由、实现登录后跳转、携带参数跳转 |
💡 最后提醒
- 所有响应式数据必须在
setup()或<script setup>中声明。 - 模板中不要写复杂逻辑,用
computed或方法封装。 - 组件通信优先用 props/emit,跨级再考虑
provide/inject。 - 路由编程题一定要动手写一遍,光看不动手容易漏细节!
祝你考试顺利,轻松拿下高分!🎉
如果你觉得这篇指南有帮助,欢迎点赞、收藏、转发给同学~