vue考试速通

42 阅读5分钟

📘 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 类:当 isActivetrue 时,添加 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. 响应式数据:refreactive

(1)ref
import { ref } from 'vue'
const count = ref(0)
  • 作用:创建一个响应式的引用对象,适用于基本类型(number、string)或对象。

  • 特点

    • <script setup> 中访问/修改需用 .valuecount.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) 无效)
    • 无法自动解包(但模板中可直接用属性)
🔍 区别总结:
对比项refreactive
适用类型基本类型、对象仅对象/数组
访问方式(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}`
})
  • 作用:定义一个依赖其他响应式数据的派生值,具有缓存性。
  • 缓存机制:只要 firstNamelastName 没变,多次访问 fullName 不会重新计算。
  • 适用场景:格式化显示、过滤列表、拼接字符串等。
(2)侦听器
import { watch } from 'vue'
watch(count, (newVal, oldVal) => {
  console.log(`计数从 ${oldVal} 变为 ${newVal}`)
})
  • 作用监听某个响应式数据的变化,并在变化时执行副作用(如发请求、打日志)。

  • 与 computed 区别

    • computed 返回值,用于模板展示;
    • watch 执行操作,用于逻辑处理。
  • 高级用法:可监听多个数据、深度监听对象({ deep: true })、立即执行({ immediate: true }


第三章:条件渲染、列表与事件

1. v-ifv-show

<div v-if="isLoggedIn">欢迎回来!</div>
<div v-show="showTips">提示信息</div>
  • v-if

    • 作用:根据表达式真假创建或销毁 DOM 元素
    • 性能:切换开销大(涉及组件生命周期),但初始渲染快。
    • 适用:条件很少改变的场景(如权限判断)。
  • v-show

    • 作用:始终渲染 DOM,通过 display: none 控制显隐。
    • 性能:初始渲染慢(DOM 已存在),但切换快。
    • 适用:频繁切换的场景(如 tab 切换)。

❗ 注意:v-ifv-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="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') // 注入数据
  • 作用:跳过中间组件,实现祖先 ↔ 后代的数据传递。
  • 响应式:若提供的是 refreactive,则注入方也能响应变化。
  • 适用场景:全局配置(如主题、语言)。

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>
  • #headerv-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:路由配置数组,每项包含 pathcomponent、可选 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
  • 路由编程题一定要动手写一遍,光看不动手容易漏细节!

祝你考试顺利,轻松拿下高分!🎉
如果你觉得这篇指南有帮助,欢迎点赞、收藏、转发给同学~