Visual LabINTERACTIVE LEARNING
框架原理精校教程

Vue 3 核心知识

以模板、ref、reactive、v-model 与组件通信为主线整理 Vue 3 日常开发知识。

Vue 3Composition API组件
入门预计 20 分钟查看源文 ↗

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') //触发
  1. 绑定其他属性
<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 中,refreactive 都是用于创建响应式数据的函数,但它们有一些重要区别:

基本使用方式

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 时,会自动解包

性能考虑

两者在性能上没有显著差异,选择主要基于使用场景和个人偏好。

最佳实践建议

  1. 对于基本类型值,优先使用 ref
  2. 对于对象/集合,如果整个对象需要响应式,使用 reactive
  3. 在组合函数中返回数据时,通常使用 ref 以便使用者可以解构而不失去响应性
  4. 在模板中,ref 会自动解包,所以两者使用体验相同

理解这些区别可以帮助你在 Vue3 开发中更合理地选择响应式 API。