简单的聊一聊Vue中如何使用 Ref 和 Reactive 声明响应式数据

在使用Options API时声明响应式数据非常简单。data选项中的所有内容都会自动变为响应式,并在模板中可用。唯一需要注意的是将data设置为一个函数,并防止在所有组件实例之间共享状态。

使用Composition API并不那么简单。状态声明必须明确地使用两个可用的实用函数(ref和reactive)来完成,并且在开始时需要注意多个特殊情况。

Reactive

让我们从简单的开始,Reactive。它接受一个对象或数组,并使用JavaScript代理使其具有响应性。

go 复制代码
import { reactive } from 'vue'

const state = reactive({ count: 0 })

State 变量的行为与普通对象完全相同。

go 复制代码
<script setup>
import { reactive } from 'vue'

const state = reactive({ count: 0 })

function increment() {
  state.count++
}
</script>

<template>
  <button @click="increment">
    {{ state.count }}
  </button>
</template>

同样适用于具有多个层级的对象。

这很简单!但是有个问题。这只适用于复杂类型( Objects 和 Arrays )和集合类型( Maps 和 Sets )。对于原始类型如 string 、 number 或 boolean ,我们需要采用不同的方法。

Ref

为了克服这个限制,我们需要使用 ref 实用工具。声明方式与响应式类似。

go 复制代码
import { ref } from 'vue'

const count = ref(0)

Ref 接受一个值并返回一个响应式对象。该值在对象内部以 .value 属性的形式返回对应的值。

go 复制代码
const count = ref(0)

console.log(count) // { value: 0 }
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

在模板中使用时,不需要 .value

go 复制代码
<script setup>
import { ref } from 'vue'

const count = ref(0)

function increment() {
  count.value++
}
</script>

<template>
  <button @click="increment">
    {{ count }} // no .value needed
  </button>
</template>

但要小心!这只适用于顶级属性。以下代码片段将产生 object Object

go 复制代码
// DON'T DO THIS
<script setup>
import { ref } from 'vue'

const object = { foo: ref(1) }

</script>

<template>
  {{ object.foo + 1 }}  // [object Object]
</template>

为了解决这个问题,我们需要将 foo 设置为顶级属性。

go 复制代码
<script setup>
import { ref } from 'vue'

const object = { foo: ref(1) }
const { foo } = object
</script>

<template>
  {{ foo + 1 }}  // This works as expected
</template>

请注意,对于数组和集合类型,也需要使用 .value 。

go 复制代码
const books = reactive([ref('Book title')])

console.log(books[0].value) // need .value here

const map = reactive(new Map([['count', ref(0)]]))

console.log(map.get('count').value) // need .value here

非响应性数据

以前声明非响应式数据并不直观。通常所有内容都声明在data中,这会创建不必要的观察者并导致轻微(可以忽略不计)的性能下降。

go 复制代码
<script setup>
const path = `path/to/image`;
</script>

<template>
  <img :src='path' />
</template>

Readonly(只读)

可以使用 readonly 来防止对状态进行更改。它接受一个对象(响应式或普通)或一个ref,并返回一个不可变的代理。

go 复制代码
const state = reactive({ count: 0 })

const copy = readonly(state)

state.count++ // Works fine

copy.count++ // Fails with a warning

结束

由于文章内容篇幅有限,今天的内容就分享到这里,文章结尾,我想提醒您,文章的创作不易,如果您喜欢我的分享,请别忘了点赞和转发,让更多有需要的人看到。同时,如果您想获取更多前端技术的知识,欢迎关注我,您的支持将是我分享最大的动力。我会持续输出更多内容,敬请期待。

相关推荐
程序员黑豆6 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC7 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea7 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望8 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少8 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0078 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis9 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝10 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师10 小时前
新兴多智能体系统的模式与问题
前端
用户0595401744611 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css