Vue3中ref和reactive的使用场景
一、核心区别
特性refreactive数据类型基本类型 + 对象/数组(自动解包)仅对象/数组响应式原理通过 .value 触发响应直接代理对象模板中使用自动解包(无需 .value)直接访问属性解构/传递保持响应性需用 toRefs 保持响应性
二、使用场景与案例
1. ref 的典型场景
(1) 管理基本类型值- import { ref } from 'vue'
- // 计数器(数字)
- const count = ref(0)
- const increment = () => {
- count.value++ // 修改值必须用 .value
- }
- // 开关状态(布尔值)
- const isOpen = ref(false)
- const toggle = () => {
- isOpen.value = !isOpen.value
- }
复制代码 (2) 引用 DOM 元素- <template>
- <input ref="inputRef" />
- </template>
- <script setup>
- import { ref, onMounted } from 'vue'
- const inputRef = ref(null)
- onMounted(() => {
- inputRef.value.focus() // 访问 DOM 元素
- })
- </script>
复制代码 (3) 需要整体替换对象/数组- const user = ref({ name: 'Alice', age: 25 })
- // 替换整个对象
- user.value = { name: 'Bob', age: 30 }
- const list = ref(['apple', 'banana'])
- // 替换整个数组
- list.value = ['orange', 'grape']
复制代码 2. reactive 的典型场景
(1) 复杂表单对象- import { reactive } from 'vue'
- const form = reactive({
- username: '',
- password: '',
- rememberMe: false
- })
- // 直接修改属性(无需 .value)
- form.username = 'John'
复制代码 (2) 嵌套数据结构- const nestedData = reactive({
- user: {
- profile: {
- name: 'Alice',
- address: {
- city: 'Shanghai'
- }
- }
- }
- })
- // 深层嵌套修改仍保持响应性
- nestedData.user.profile.address.city = 'Beijing'
复制代码 (3) 数组操作- const items = reactive(['a', 'b', 'c'])
- // 直接修改元素
- items[0] = 'z' // 响应式更新
- items.push('d') // 使用数组方法
复制代码 三、关键操作指南
1. 正确赋值/修改
ref 示例:- const count = ref(0)
- // ✅ 正确修改
- count.value = 10
- // ❌ 错误!直接赋值会覆盖 ref 对象
- count = 10
复制代码 reactive 示例:- const state = reactive({ count: 0 })
- // ✅ 正确修改属性
- state.count = 10
- // ❌ 错误!直接替换对象会失去响应性
- state = { count: 20 }
- // ✅ 保持响应性的对象替换方式
- Object.assign(state, { count: 20 })
复制代码 2. 处理响应式丢失
(1) 解构 reactive 对象- const state = reactive({ x: 1, y: 2 })
- // ❌ 解构后失去响应性
- const { x, y } = state
- // ✅ 使用 toRefs 保持响应性
- const { x, y } = toRefs(state)
- x.value = 10 // 现在修改有效
复制代码 (2) 函数间传递- // ✅ 传递整个 reactive 对象
- const user = reactive({ name: 'Alice' })
- updateUser(user)
- function updateUser(userObj) {
- userObj.name = 'Bob' // 修改仍响应
- }
- // ✅ 传递 ref 对象
- const count = ref(0)
- increment(count)
- function increment(numRef) {
- numRef.value++
- }
复制代码 四、性能与最佳实践
优先选择:
- 基本类型 →
- 复杂对象 →
- 需要灵活替换 →(即使存储对象)
注意事项:
- 避免在中嵌套(除非明确需要)
- 对数组进行索引操作时,建议使用变更方法(等)
- 大型数据集考虑/提升性能
五、综合对比案例
- <script setup>
- import { ref, reactive } from 'vue'
- // ref 管理用户ID(基本类型)
- const userId = ref(123)
- // reactive 管理用户详情(对象)
- const userDetail = reactive({
- name: 'Alice',
- permissions: ['read', 'write']
- })
- // 修改操作示例
- const updateUser = () => {
- // 修改 ref
- userId.value = 456
-
- // 修改 reactive 对象
- userDetail.name = 'Bob'
- userDetail.permissions.push('delete')
- }
- // 替换整个对象的最佳实践
- const resetUser = () => {
- // ref 可以直接替换
- userId.value = 0
-
- // reactive 应该合并属性而非直接赋值
- Object.assign(userDetail, {
- name: 'Guest',
- permissions: []
- })
- }
- </script>
复制代码 通过以上案例可以看出:更适合管理独立值和需要完全替换的场景,而在处理复杂对象结构时更直观。根据具体需求灵活选择,可显著提升代码可维护性。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
来源:https://www.jb51.net/javascript/3398329op.htm
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|