框架原理精校教程
Vue 3 核心知识
以模板、ref、reactive、v-model 与组件通信为主线整理 Vue 3 日常开发知识。
Vue3知识点
模板语法
文本插值
<div>{{ 'text' }}</div>
指令
内置指令 指令的格式

事件 v-on
属性 v-bind
动态的绑定一个或多个 attribute,也可以是组件的 prop。
缩写:
:或者.(当使用.prop修饰符)- 值可以省略 (当 attribute 和绑定的值同名时,需要 3.4+ 版本)
期望:
any (带参数) | Object (不带参数)参数:
attrOrProp (可选的)修饰符
.camel- 将短横线命名的 attribute 转变为驼峰式命名。.prop- 强制绑定为 DOM property (3.2+)。.attr- 强制绑定为 DOM attribute (3.2+)。
<!-- 完整 -->
<div v-bind:id="dynamicId"></div>
<!-- 简写 -->
<div :id="dynamicId"></div>
<!-- 同名简写 vue3.4+ -->
<!-- 与 :id="id" 相同 -->
<div :id></div>
<!-- 这也同样有效 -->
<div v-bind:id></div>
<!-- 使用修饰符 -->
<div :someProperty.prop="someObject"></div>
<!-- 等同于 -->
<div .someProperty="someObject"></div>
<!-- 动态 attribute 名的缩写 -->
<button v-bind:[key]="value"></button>
<button :[key]="value"></button>
动态参数值的限制
动态参数中表达式的值应当是一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。其他非字符串的值会触发警告。
动态参数语法的限制
动态参数表达式因为某些字符的缘故有一些语法限制,比如空格和引号,在 HTML attribute 名称中都是不合法的,推荐使用计算属性替换复杂的表达式
<!-- 这会触发一个编译器警告 -->
<a :['foo' + bar]="value"> ... </a>
响应式
ref
- 深层响应性,亦即嵌套的属性也是具有响应性的
- 通过.value访问值,但在模板中不需要,会被自动解包
reactive
丢失响应式的3种情况
const state = reactive({ count: 0 })
// n 是一个局部变量,同 state.count
// 失去响应性连接
let n = state.count
// 不影响原始的 state
n++
// count 也和 state.count 失去了响应性连接
let { count } = state
// 不会影响原始的 state
count++
// 该函数接收一个普通数字,并且
// 将无法跟踪 state.count 的变化
callSomeFunction(state.count)
ref底层也使用reactive来包装对象,实现响应式
v-model
自定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件
<ChildComponent v-model="pageTitle" />
//<!-- 是以下的简写: -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
// ChildComponent.vue
emits('update:modelValue') //触发
- 绑定其他属性
<ChildComponent v-model:title="pageTitle" />
// 是以下的简写: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
//绑定多个,可以用于替代vue2中的sync修饰符
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
// 是以下的简写: -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>
// ChildComponent.vue
emits('update:title') //触发
emits('update:content') //触发
//绑定自定义组件时需要手动触发,绑定表单组件时,不需要
为什么需要使用hooks?
💡 提示
在有状态的情况下,也可以使用多个较小且逻辑独立的单元来组合形成复杂的逻辑 逻辑/代码复用是hooks的原因和目的 hooks函数中允许使用响应式,以及生命周期函数
Vue3 中 ref 和 reactive 的区别
在 Vue3 的 Composition API 中,ref 和 reactive 都是用于创建响应式数据的函数,但它们有一些重要区别:
基本使用方式
ref:
import { ref } from 'vue'
const count = ref(0) // 创建 ref
console.log(count.value) // 访问值
count.value++ // 修改值
reactive:
import { reactive } from 'vue'
const state = reactive({ count: 0 }) // 创建 reactive 对象
console.log(state.count) // 访问属性
state.count++ // 修改属性
主要区别
| 特性 | ref | reactive |
|---|---|---|
| 数据类型 | 可以包装任何值(原始值、对象、数组等) | 只能用于对象(包括数组) |
| 访问方式 | 需要通过 .value 访问 |
直接访问属性 |
| 解构/展开 | 保持响应性 | 会失去响应性 |
| 模板中使用 | 自动解包(无需 .value) | 直接使用 |
| TypeScript 支持 | 更好的类型推断 | 需要定义接口 |
使用场景
使用 ref 的情况:
- 需要包装原始值(字符串、数字、布尔值等)
- 需要保持对单个值的引用
- 需要在组合函数中返回响应式值
使用 reactive 的情况:
- 需要创建一个响应式对象(多个相关属性)
- 需要嵌套的响应式结构
- 当你想避免频繁使用
.value时
转换关系
- 可以使用
reactive包装ref,此时会自动解包:
const count = ref(0)
const state = reactive({ count })
console.log(state.count) // 不需要 .value
- 在
reactive对象中访问ref时,会自动解包
性能考虑
两者在性能上没有显著差异,选择主要基于使用场景和个人偏好。
最佳实践建议
- 对于基本类型值,优先使用
ref - 对于对象/集合,如果整个对象需要响应式,使用
reactive - 在组合函数中返回数据时,通常使用
ref以便使用者可以解构而不失去响应性 - 在模板中,
ref会自动解包,所以两者使用体验相同
理解这些区别可以帮助你在 Vue3 开发中更合理地选择响应式 API。