当前位置: 首页 > news >正文

前端面经-VUE3篇--vue3基础知识(一)插值表达式、ref、reactive

目录

一、 插值表达式

1、插值表达式 ({{}}) 的本质与作用:

2、与 Vue 响应式系统关系:

二、指令

 1、什么是 Vue 指令?

2、指令的分类

 1、内置指令

① 内容绑定:v-text 和 v-html

 ② 属性绑定:v-bind

 ③ 事件绑定:v-on

 ④ 条件渲染:v-if、v-else-if、v-else

⑤ 列表渲染:v-for

⑥ 双向绑定:v-model

⑦ 性能优化:v-once、v-memo

 ⑧ 其他指令

v-pre:跳过模板编译阶段(提升渲染性能)。

 v-cloak:防止插值表达式闪烁(未编译完毕时隐藏元素)。

2、自定义指令(用户扩展)

3、javascript表达式

4、动态参数

1、什么是「动态参数」?

2、动态参数值的限制:

3、参数语法的限制:

 三、响应式基础

 1、ref()

1、 在模板中如何使用?

 2、模板 ref(获取DOM元素引用)

3、 为 ref() 标注类型

1、为什么要为 ref() 标注类型?

 2、如何为 ref() 标注类型?

 方法一:显式标注类型(推荐)

 方法二:类型推导(隐式标注)

3、复杂类型如何标注类型?

 4、模板 ref 的类型标注

2、reactive()

 1、reactive() 基本用法

2、在模板中使用:

3、reactive() 深层响应式特性

 4、ref 解包

 为什么会存在额外的 ref 解包?

需要注意的问题(⚠️重要)

 问题1:在赋值新值时仍保持 ref 特性

 问题2:解构赋值问题

数组和集合的注意事项 

在模板中解包的注意事项​

5、为 reactive 标注类型

方式一:使用接口(Interface)标注类型(推荐)

 方式二:使用类型别名(type)标注类型

方式三:显式类型断言(不推荐,偶尔使用)

为复杂嵌套数据标注类型的实践示例

使用泛型标注 reactive 的常见错误


我们知道vue的特点是

  • 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。

  • 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。 

最显著的一个特点就是响应式,那么引出插值表达式

一、 插值表达式

1、插值表达式 ({{}}) 的本质与作用:

插值表达式是 Vue 模板语法的一部分,它告诉 Vue:

这里需要绑定数据,请自动更新这个区域的内容。<div>{{ message }}</div>

插值用于显示在元素内部的文本内容

本质上是在告诉 Vue:

  • “请帮我监听响应式数据对象中的 message 字段。”

  • “当它的值发生变化时,请自动更新这个 <div> 中显示的内容。”

作用:

  • 数据绑定(Data Binding)

    • 绑定响应式数据的值,使得视图总能与数据保持同步。

  • 自动更新 UI

    • 数据变化后,Vue 会自动地更新插值表达式对应的 DOM 区域。

  • 便捷显示数据

    • 简单直观地展示动态内容,减少繁琐的 DOM 操作。

 除了基本变量名,插值表达式内还可以使用简单的 JavaScript 表达式:

<div>{{ count * 2 }}</div>

<div>{{ isLoggedIn ? "已登录" : "未登录" }}</div>

2、与 Vue 响应式系统关系:

插值表达式依靠 Vue 响应式系统:

  • Vue 内部通过 refreactive 等 API 使数据变得响应式。

  • 当响应式数据变化,Vue 自动触发页面重新渲染,更新插值内容。

有小伙伴回想Vue 已经响应式了,为何还用插值?

  • Vue 是响应式框架,响应式的含义是数据变化后自动更新视图,而插值表达式 ({{}}) 就是这种自动更新机制体现到模板上的一种方式

  • 插值表达式让数据的自动变化直接体现在页面显示上,开发者无需手动编写监听与更新代码。

 我们知道了插值表达式以后要注意两点

1、插值表达式无法用在 HTML 属性中  <div class="{{className}}">无效</div>

因此我们等会要学习指令,指令使得我们的元素的属也可以变成响应式

2、 插值表达式仅适合简单逻辑

  • 插值中不要编写过于复杂的表达式。

  • 复杂逻辑建议抽离到 computed 或方法中

二、指令

 1、什么是 Vue 指令?

在 Vue 中,指令(Directives) 是带有前缀 v- 的特殊属性,用于在模板中提供特定的行为或功能。

Vue 的指令本质上是

  • 一种模板语法扩展。

  • 用来在模板中声明式地控制 DOM 的行为、渲染逻辑以及响应式交互。

2、指令的分类

Vue 指令分为:

  • 内置指令(Vue 自带):如 v-ifv-for 等。

  • 自定义指令(用户定义):可根据需求自定义,如:v-focus

 1、内置指令

① 内容绑定:v-textv-html

 v-text:更新元素的文本内容,与插值表达式作用类似,但会覆盖元素内所有内容。

 <div v-text="message"></div>
<!-- 相当于 -->
<div>{{ message }}</div>

 v-html:输出原始 HTML 内容(会解析HTML标签)。

 插值表达式会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用v-html指令

假如你的数据是这样的:

 data() {return {rawHtml: '<span style="color: red">这是红色字体!</span>'}
}

 使用插值表达式 ({{ }}):

<!-- 普通插值会直接输出HTML代码,而非解析它 -->
<div>{{ rawHtml }}</div>

页面上会直接显示:<span style="color: red">这是红色字体!</span>

 (HTML标签会显示成原样,而不会解析为真正的HTML元素)

 使用 v-html 指令

<div v-html="rawHtml"></div>

页面实际渲染结果:

<div><span style="color: red">这是红色字体!</span>
</div> 

这次页面会真正地把字符串解析为HTML元素,显示为:

这是红色字体!(字体颜色为红色) 

使用 v-html 时必须特别注意安全问题:

  • Vue 使用 v-html 时会解析 HTML 字符串,但不会对内容进行安全过滤

  • 如果插入了用户提供的不可信内容(如用户留言、评论等),可能引发 XSS(跨站脚本攻击)风险

 ② 属性绑定:v-bind

 作用:动态绑定元素的属性或组件的 props。

<!-- 完整写法 -->
<a v-bind:href="link">链接</a>
<!-- 简写 -->
<a :href="link">链接</a>

常用场景:动态class绑定、style绑定、组件传值。

 <div :class="{ active: isActive }"></div>
 ③ 事件绑定:v-on

 作用:为元素绑定事件监听器,如 click、submit 等。

<!-- 完整写法 -->
<button v-on:click="doSomething">按钮</button>
<!-- 简写 -->
<button @click="doSomething">按钮</button>
  • 事件修饰符(常用):

修饰符作用
.stop阻止事件冒泡
.prevent阻止默认事件
.once只触发一次
.capture事件捕获模式
 ④ 条件渲染:v-ifv-else-ifv-else

根据条件渲染元素:

<div v-if="isActive">活跃状态</div>
<div v-else>未活跃状态</div>

注意v-if 会完全删除或重建 DOM 节点。

补充:v-show

  • v-show 仅控制元素的 display 属性,不删除 DOM。

  • 适用于频繁切换场景。

<div v-show="isVisible">显示内容</div>
⑤ 列表渲染:v-for

循环遍历数组或对象:必须指定 key 属性来优化更新效率。

<ul><li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.name }}</li>
</ul>
⑥ 双向绑定:v-model
  • 将表单控件与数据自动双向绑定,数据和视图实时同步:

<input v-model="username" placeholder="请输入用户名">
  • 常用修饰符:

修饰符作用
.lazy在 input 失去焦点或回车时才同步
.number将输入转为数值类型
.trim自动过滤首尾空白字符
<input v-model.number="age">
⑦ 性能优化:v-oncev-memo
  • v-once:只渲染一次,不再响应后续数据变化:<span v-once>{{ staticContent }}</span>

  • v-memo (Vue 3.2+):精确控制渲染,只有依赖的值变化时才重新渲染:<div v-memo="[key]">{{ key }}</div>

 ⑧ 其他指令
  • v-pre:跳过模板编译阶段(提升渲染性能)。

 <span v-pre>{{ raw }}</span> <!-- 直接显示 {{ raw }} -->

 v-cloak:防止插值表达式闪烁(未编译完毕时隐藏元素)。
<style>
[v-cloak] { display: none; }
</style>
<div v-cloak>{{ msg }}</div>

2、自定义指令(用户扩展)

当内置指令不能满足需求时,用户可以创建自定义指令。

 注册示例(Vue 3.x)

const app = Vue.createApp({})app.directive('focus', {mounted(el) {el.focus()}
})

使用自定义指令:

<input v-focus>

指令的生命周期钩子(自定义指令专用)

钩子函数描述
created指令绑定元素后调用
beforeMount元素插入到 DOM 前调用
mounted元素插入到 DOM 后调用
beforeUpdate更新前调用
updated更新后调用
beforeUnmount元素卸载前调用
unmounted元素卸载后调用

3、javascript表达式

在 Vue 中,模板语法本质上是基于 JavaScript 表达式的

也就是说:

  • 在 Vue 模板的插值表达式 ({{}}) 或指令(如 v-bindv-ifv-for)中,实际填写的内容本质上都是 JavaScript 表达式

  • Vue 在渲染模板时会自动对这些 JavaScript 表达式进行求值,并将结果渲染到视图上。

JavaScript表达式 (Expression) 是一种产生值的代码片段。它的特点是:

  • 任何能返回一个值的语句都是表达式。

  • 表达式求值后一定会得到一个具体的值。

  • 表达式本身可以由:

    • 字面量(Literal) 如数字、字符串。

    • 变量引用(如:x)。

    • 运算符组合(如:a + b)。

    • 函数调用(如:getName())。

    • 三元运算符(如:x > 1 ? 'Yes' : 'No')等组成。

// 字面量
42;                    // 数字表达式
"Hello";               // 字符串表达式// 算术表达式
1 + 2;                 // 求值为 3// 逻辑表达式
a > b && c < d;        // 返回 true 或 false// 三元表达式
isActive ? '是' : '否';// 函数调用表达式
getUsername();         // 返回调用函数的返回值

 在 Vue 模板中只能使用表达式,不能使用语句

<!-- 无效,会报错 -->
<div>{{ if(a > b) { return a; } }}</div>

4、动态参数

1、什么是「动态参数」?

传统绑定是静态的(固定属性名):<a :href="url">链接</a>
动态参数的作用是,允许动态决定绑定哪个属性

 <a :[attributeName]="url">链接</a>

此时:

  • [attributeName] 是一个动态参数。

  • 它的实际值由 attributeName 这个数据属性的值决定。

2、动态参数值的限制:

动态参数表达式的值,必须是字符串或 null,其他类型的值(如数字、对象、布尔值)会报错。

3、参数语法的限制:

  • 动态参数内的表达式只允许简单表达式,不允许复杂的 JavaScript 语句。

  • 比如不能直接写三元表达式、函数调用、对象属性访问等复杂逻辑。

 示例:假设有个按钮组件,动态绑定事件

<template><button @[eventType]="onTrigger">触发按钮</button>
</template><script setup>
import { ref } from 'vue'const eventType = ref('click') // 可修改为其他事件如 mouseover、dblclickfunction onTrigger() {alert('事件触发!')
}
</script>
  • 动态决定绑定的事件类型。

  • 极大增加组件的可复用性和灵活性。

 三、响应式基础

 1、ref()

ref() 是 Vue 3 中一个重要的响应式 API,专门用来创建响应式数据。它的全称为 reference(引用),作用是将一个基本类型数据或对象包裹成响应式对象,使数据能够在发生变化时自动通知视图更新。

特点

  • 可用来处理任何类型(基本类型、对象、数组)。

  • 通常更常用于基本类型数据(例如数字、字符串、布尔值)。

  • 访问数据时需通过 .value 属性。

import { ref } from 'vue'
const count = ref(0)  // 创建一个响应式数据,初始值为 0

访问数据时:console.log(count.value) // 输出 0

修改数据:count.value++
console.log(count.value) // 输出 1

 ⚠️ 注意:
ref() 返回的是一个对象,所以必须使用 .value 来访问真正的值

1、 在模板中如何使用?

在模板中,Vue 自动帮你解包 .value

<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {count.value++
}
</script>
<template><div>{{ count }}</div> <!-- 这里不需要写 count.value,模板会自动帮你解包 --><button @click="increment">+1</button>
</template>
  • 模板中:直接使用 count 即可。

  • JavaScript 中:需要 count.value

 ref 如何处理对象类型?

 虽然推荐使用 ref() 来处理基本类型数据,但也可以用它创建对象或数组:

const obj = ref({ name: 'Tom', age: 20 })
console.log(obj.value.name)  // Tom
obj.value.age = 21  // 依然是响应式更新

但注意:

  • 使用 ref 创建的对象类型数据本质上是在 ref 中存储一个 reactive 对象

  • 若直接替换对象时必须用 .value

// 正确方式:
obj.value = { name: 'Jerry', age: 22 }

⚠️ 若想避免频繁使用 .value,可用 reactive 替代:

const obj = reactive({ name: 'Tom', age: 20 })

 2、模板 ref(获取DOM元素引用)

 在模板里使用 ref 属性获取 DOM 元素或子组件的引用:

<template><input ref="inputRef"><button @click="focusInput">聚焦输入框</button>
</template><script setup>
import { ref } from 'vue'const inputRef = ref(null)function focusInput() {inputRef.value.focus()  // 获取到真实的DOM元素并调用方法
}
</script>
  • inputRef 会绑定到对应的DOM或子组件实例上。

  • 通常用于直接操作DOM或子组件(如:聚焦、调用子组件方法)。

3、 为 ref() 标注类型

1、为什么要为 ref() 标注类型?

默认情况下,Vue 3 已经提供了对 TypeScript 的完整支持,但在使用 ref() 创建响应式数据时,明确地标注类型会带来更多的好处

  • 提升代码可读性

    • 其他开发者一看就知道你的数据类型是什么。

  • 获得更好的类型检查

    • IDE 能精准识别类型错误,避免潜在Bug。

  • IDE 更好的自动补全支持

    • 更流畅的开发体验,提高效率。

 2、如何为 ref() 标注类型?
 方法一:显式标注类型(推荐)

使用泛型明确指定类型:

import { ref } from 'vue'// 标注为数字类型的ref
const count = ref<number>(0)// 标注为字符串类型的ref
const name = ref<string>('Vue')// 标注为对象类型的ref
interface User {name: stringage: number
}const user = ref<User>({name: 'Tom',age: 30
})
 方法二:类型推导(隐式标注)

 如果你没有显式指定泛型类型,Vue 会根据初始值自动推导类型

import { ref } from 'vue'// 自动推断 count 为 number 类型的 Ref<number>
const count = ref(0)// 自动推断 name 为 string 类型的 Ref<string>
const name = ref('Vue')

但注意

  • 如果初始值是 nullundefined,Vue 会推导成宽泛类型 Ref<null>Ref<undefined>,这通常不是我们想要的:

 const name = ref(null) // 推断为 Ref<null>,一般意义不大

 这种情况建议你显式标注类型:

// 更好的写法:
const name = ref<string | null>(null)
3、复杂类型如何标注类型?

 常用接口或类型别名定义复杂对象,再传给 ref()

 接口类型示例

interface Article {title: stringcontent: stringlikes: number
}// 显式指定 Article 类型
const article = ref<Article>({title: 'Vue 3 指南',content: 'Vue 3 的核心...',likes: 0
})

 类型别名示例

type Status = 'success' | 'error' | 'loading'const status = ref<Status>('loading')
 4、模板 ref 的类型标注

模板 ref 是指用于绑定到 DOM 元素或组件引用的 ref

<template><input ref="inputRef" />
</template><script setup lang="ts">
import { ref, onMounted } from 'vue'// HTMLInputElement 标注 DOM元素类型
const inputRef = ref<HTMLInputElement | null>(null)onMounted(() => {inputRef.value?.focus()
})
</script>
  • inputRef 必须初始化为 null,因为挂载前没有元素。

  • 需要标注为 HTMLElement 或具体的 DOM 元素类型,如 HTMLInputElement

 4、与Ref的关系

Ref 是一个TypeScript 类型接口

  • 它用于明确地描述由 ref() 函数返回的对象的类型结构

  • 其定义为:Ref泛型接口,通过泛型参数指定存储的数据类型。

interface Ref<T> {value: T
}

 使用示例:

import { Ref, ref } from 'vue'// 显式指定count的类型为Ref<number>
const count: Ref<number> = ref(0)// 复杂类型示例:
interface User {name: stringage: number
}// 显式指定类型Ref<User>
const user: Ref<User> = ref({name: 'Vue',age: 3
})

 两者之间的关系是实现与类型声明的关系

名称类型用途
ref()函数创建一个响应式的数据对象
RefTypeScript 泛型接口描述 ref() 返回的数据的类型结构

2、reactive()

在 Vue 3 中:

  • reactive() 是一个核心的 API,用于创建一个响应式对象或数组

  • 当对象或数组的数据发生变化时,Vue 会自动更新使用该数据的视图

本质上:

  • reactive() 会将一个普通 JavaScript 对象或数组转换为响应式代理对象(Proxy)。

  • 所有对该对象属性的读取、修改操作都会被拦截,从而实现响应式更新。

 1、reactive() 基本用法

import { reactive } from 'vue'
// 创建一个响应式对象
const state = reactive({name: 'Vue',count: 0
})

 使用响应式数据:

console.log(state.name) // 输出:Vue
state.count++ // 数据更新,自动触发视图更新

2、在模板中使用:

在模板中,reactive() 创建的对象属性能直接访问:

<script setup>
import { reactive } from 'vue'const state = reactive({ name: 'Tom', age: 30 })function updateAge() {state.age++
}
</script><template><div>{{ state.name }} - 年龄: {{ state.age }}</div><button @click="updateAge">增加年龄</button>
</template>

注意

  • ref() 不同,reactive() 创建的数据访问时不需要 .value

 reactive vs ref 区别对比

特性reactive()ref()
适用类型对象或数组基础数据类型(单个值)
访问方式不需要 .value必须 .value
本质Proxy代理对象包裹基本值的响应式对象
适用场景复杂对象、数组单一基本类型数据

3、reactive() 深层响应式特性

在 Vue 3 中:

  • 使用 reactive() 创建的响应式对象默认都是深层响应式的

  • 深层响应式意味着:

    • 如果一个对象中嵌套了其他对象或数组,这些嵌套的对象或数组也会自动成为响应式

    • 不论嵌套对象有多少层,修改任何一层中的属性,都会自动触发视图的更新。

简单理解为

reactive() 会递归地将整个对象树都变为响应式

 假设我们创建一个嵌套的对象:

import { reactive } from 'vue'const state = reactive({user: {name: 'Tom',info: {age: 20,hobbies: ['篮球', '音乐']}}
})

 这时,state 整个对象树都是响应式的: 

state.user.name = 'Jerry'              // ✔️ 响应式更新
state.user.info.age = 21               // ✔️ 深层响应式更新
state.user.info.hobbies.push('阅读')   // ✔️ 数组响应式更新
  • 不需要额外手动声明嵌套数据为响应式。

  • Vue 会自动递归 Proxy 化整个嵌套结构。

 深层响应式的内部原理(Proxy递归机制)

深层响应式的实现,背后的机制是 JavaScript 的 Proxy 对象

 简化版原理:

function reactive(target) {return new Proxy(target, {get(target, key, receiver) {const res = Reflect.get(target, key, receiver)// 若获取到的值是对象,则递归 Proxy 化,形成深层响应式if (typeof res === 'object' && res !== null) {return reactive(res)}// 依赖收集track(target, key)return res},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver)// 触发更新通知trigger(target, key)return result}})
}
  • 当访问对象属性(get)时,若是嵌套对象,则会自动再次调用 reactive() 创建深层 Proxy。

  • 这样确保所有嵌套对象都实现响应式。

state.user.address.city = '北京'  // ✔️ 自动响应式

深层响应式 vs 浅层响应式

为了应对某些特定场景,Vue 也提供了浅层响应式(Shallow Reactive)

API功能深层响应式
reactive()创建响应式对象✅ 深层响应式
shallowReactive()创建浅层响应式对象❌ 只响应顶层
import { shallowReactive } from 'vue'const state = shallowReactive({user: { name: 'Tom', age: 20 }
})state.user.age = 21 // ❌ 不会触发响应式更新
state.user = { name: 'Jerry', age: 22 } // ✔️ 会触发响应式更新(只监听顶层属性)

reactive() 与解构的注意事项

reactive() 创建的响应式对象若直接解构,会导致数据丢失响应性

const state = reactive({ count: 0 })// 解构后 count 非响应式!
let { count } = statecount++  // 无法触发响应式更新!

正确方式(toRefs):

使用 Vue 提供的 toRefs() 进行解构,保持响应式:

import { reactive, toRefs } from 'vue'const state = reactive({ count: 0 })const { count } = toRefs(state)  // 转换为 ref 类型,保持响应式count.value++  // ✔️ 仍然响应式

 4、ref 解包

在 Vue 3 的响应式系统中,存在一种特别的机制称为 Ref 解包(Ref Unwrapping)

  • 当你使用 ref() 创建响应式数据时,数据被包裹在一个具有 .value 属性的对象里。

  • 在模板中使用这些数据时,Vue 会自动帮你去掉 .value,直接访问真正的数据,这个过程叫做自动解包(Automatic Unwrapping)

然而,除了模板中的自动解包外,Vue 还在一些特定场景中提供了 额外的 ref 解包机制

  • 即在一些特殊的响应式对象中(例如用 reactive() 创建的对象),如果它的属性值是一个 ref(),则访问这个属性时,Vue 会自动解包到 .value

 看一个直观的例子:

import { ref, reactive } from 'vue'const count = ref(1)// reactive 对象包含一个 ref
const state = reactive({countRef: count
})// 访问 state.countRef 时,不需要 .value,也能自动解包:
console.log(state.countRef) // 输出:1,而不是 { value: 1 }

 state.countRef 本质上是 ref 对象,但 Vue 的响应式代理会自动解包,使你无需显式使用 .value 访问。

 为什么会存在额外的 ref 解包?

额外的 ref 解包主要是为了:

  • 让开发者在使用嵌套响应式数据时更方便、直观,不必在模板外过多考虑.value的存在。

  • 特别是在构建复杂的响应式数据结构时,使代码更加简洁、直观。

如果没有这个机制:

  • 使用 reactive 对象嵌套 ref 时,每次访问内部值都必须手动使用 .value,非常麻烦。

 适用场景

 reactive() 对象的属性是 ref()

const nameRef = ref('Tom')const state = reactive({ name: nameRef })console.log(state.name) // 自动解包为 'Tom'
需要注意的问题(⚠️重要)
 问题1:在赋值新值时仍保持 ref 特性
const countRef = ref(0)
const state = reactive({ count: countRef })state.count = 10 // 这里本质上相当于 countRef.value = 10
console.log(countRef.value) // 10(依然联动变化)
 问题2:解构赋值问题
  • 如果你直接对 reactive 对象解构,则会失去响应性:

数组和集合的注意事项 

与 reactive 对象不同的是,当 ref 作为响应式数组或原生集合类型 (如 Map) 中的元素被访问时,它不会被解包:

const books = reactive([ref('Vue 3 Guide')])
// 这里需要 .value
console.log(books[0].value)const map = reactive(new Map([['count', ref(0)]]))
// 这里需要 .value
console.log(map.get('count').value)
在模板中解包的注意事项​

在模板渲染上下文中,只有顶级的 ref 属性才会被解包。

 在下面的例子中,count 和 object 是顶级属性,但 object.id 不是:

const count = ref(0)
const object = { id: ref(1) }
//因此,这个表达式按预期工作:
{{ count + 1 }}
//但这个不会:
{{ object.id + 1 }}
//渲染的结果将是 [object Object]1,因为在计算表达式时 object.id 没有被解包,仍然是一个 ref 对象。
//为了解决这个问题,我们可以将 id 解构为一个顶级属性:
const { id } = object
{{ id + 1 }}  //渲染的结果将是 2//注意
//一个需要注意的点是,如果 ref 是文本插值的最终计算值 (即 {{ }} 标签),那么它将被解包,因此以下内容将渲染为 1:
{{ object.id }}

5、为 reactive 标注类型

reactive() 标注类型通常采用以下几种方式:

方式一:使用接口(Interface)标注类型(推荐)

接口是一种定义复杂对象结构的最佳方式:

import { reactive } from 'vue'interface User {name: stringage: number
}// 明确标注 reactive 对象的类型为 User
const user = reactive<User>({name: 'Tom',age: 30
})
 方式二:使用类型别名(type)标注类型

类型别名用法与接口类似,适合定义简单或复合类型:

import { reactive } from 'vue'type Status = 'success' | 'error' | 'loading'interface ResponseData {status: Statusdata: string[]
}// 使用类型别名与接口结合
const response = reactive<ResponseData>({status: 'loading',data: []
})
方式三:显式类型断言(不推荐,偶尔使用)

显式类型断言能快速定义类型,但会牺牲类型检查严谨性,一般不推荐:

import { reactive } from 'vue'const state = reactive({name: 'Vue',version: 3
} as { name: string; version: number })

⚠️ 注意:

  • 类型断言会略过类型校验,可能隐藏错误。

为复杂嵌套数据标注类型的实践示例

示例:

import { reactive } from 'vue'interface Address {city: stringzipCode: string
}interface User {name: stringaddress: Address
}const user = reactive<User>({name: 'Jerry',address: {city: 'Shanghai',zipCode: '200000'}
})
  • 明确的类型标注帮助 IDE 提供更精确的属性提示。

使用泛型标注 reactive 的常见错误

有些开发者可能尝试这样做(但这是错误的):

const user: User = reactive({ name: 'Tom', age: 20 }) // ❌ 错误!
  • reactive() 返回的类型并非 User 本身,而是 User 类型的 Proxy 代理。

  • 正确的写法是用泛型指定:

const user = reactive<User>({ name: 'Tom', age: 20 }) // ✅ 正确

 

相关文章:

  • 【Hive入门】Hive性能调优之Join优化:深入解析MapJoin与Sort-Merge Join策略
  • PHP-session
  • word交叉引用图片、表格——只引用编号的处理方法
  • Typora语法转换与Vue双向数据绑定:延迟更新机制的异曲同工之妙
  • Mybatis学习笔记
  • MSP430G2553驱动0.96英寸OLED(硬件iic)
  • 【AI面试准备】Azure DevOps沙箱实验全流程详解
  • 基于bert预训练模型的垃圾短信分类系统
  • React useMemo函数
  • 中小企业MES系统数据库设计
  • RabbitMQ的交换机
  • 【阿里云大模型高级工程师ACP习题集】2.9 大模型应用生产实践(上篇)
  • 超长8分钟Suno V4.5 – 支持一首歌多风格转换啦~~~
  • Nginx部署Vue+ElementPlus应用案例(基于腾讯云)
  • PDF转换工具xpdf-tools-4.05
  • 敏感词 v0.25.0 新特性之 wordCheck 策略支持用户自定义
  • 【安装指南】Chat2DB-集成了AI功能的数据库管理工具
  • 论文阅读笔记——TesserAct: Learning 4D Embodied World Models
  • 【安装指南】Centos7 在 Docker 上安装 RabbitMQ4.0.x
  • 【无需docker】mac本地部署dify
  • 苏州一直升机坠落致1死4伤,事故调查正展开
  • 五一首日出沪高峰,G1503高东收费站上午车速约30公里/小时
  • 国务院食安办:加强五一假期食品生产、销售、餐饮服务环节监管
  • 水利部将联合最高检开展黄河流域水生态保护专项行动
  • 看见“看得见的手”,看见住房与土地——读《央地之间》
  • 王毅会见泰国外长玛里:坚决有力打击电诈等跨境犯罪