响应式
1. ref() 函数
作用:
创建响应式的数据引用,主要用于基本类型(字符串、数字、布尔值等),也可以用于对象。
特点:
- 返回一个具有
.value属性的响应式对象 - 在模板中自动解包(无需
.value) - 在JavaScript中需要通过
.value访问
示例:
javascript
import { ref } from 'vue'
// 基本类型
const count = ref(0)
console.log(count.value) // 0
count.value = 1
// 对象类型
const user = ref({ name: '张三', age: 25 })
user.value.name = '李四'
// 在模板中自动解包
// <div>{{ count }}</div> ✅ 不需要 .value2. reactive() 函数
作用:
创建响应式的对象或数组,返回一个Proxy代理对象。
特点:
- 只能用于对象类型(对象、数组、Map、Set等)
- 直接访问和修改属性,不需要
.value - 深度响应式(嵌套对象也会被响应式处理)
示例:
javascript
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: {
name: '张三',
age: 25
},
hobbies: ['读书', '运动']
})
// 直接访问和修改
console.log(state.count) // 0
state.count = 1
state.user.name = '李四'
state.hobbies.push('编程')
// 响应式是深度的
state.user.age = 26 // 也会触发响应3. toRef() 函数
作用:
将响应式对象的某个属性转换为ref,保持与源属性的响应式连接。
特点:
- 创建的ref与源属性保持同步
- 修改ref会更新源对象,修改源对象也会更新ref
- 用于处理props或reactive对象的单个属性
示例:
javascript
import { reactive, toRef } from 'vue'
const state = reactive({
name: '张三',
age: 25
})
// 将state.name转换为ref
const nameRef = toRef(state, 'name')
// 修改ref会影响源对象
nameRef.value = '李四'
console.log(state.name) // '李四'
// 修改源对象也会影响ref
state.name = '王五'
console.log(nameRef.value) // '王五'
// 常用于处理props
const props = defineProps(['title'])
const titleRef = toRef(props, 'title')4. toRefs() 函数
作用:
将响应式对象的所有属性转换为ref对象集合。
特点:
- 保持与源对象所有属性的响应式连接
- 方便在组合式函数中返回响应式状态
- 支持解构赋值而不丢失响应性
示例:
javascript
import { reactive, toRefs } from 'vue'
const state = reactive({
name: '张三',
age: 25,
score: 90
})
// 转换为ref对象
const refs = toRefs(state)
// refs: { name: Ref, age: Ref, score: Ref }
// 修改ref会影响源对象
refs.name.value = '李四'
console.log(state.name) // '李四'
// 常用场景:解构响应式对象而不丢失响应性
const { name, age } = toRefs(state)
name.value = '王五' // ✅ 保持响应性
// 对比:直接解构会丢失响应性
const { name, age } = state
name = '赵六' // ❌ 失去响应性对比总结
| 特性 | ref() | reactive() | toRef() | toRefs() |
|---|---|---|---|---|
| 适用类型 | 基本类型+对象 | 仅对象类型 | 响应式对象的属性 | 响应式对象的所有属性 |
| 返回值 | Ref对象 | Proxy对象 | Ref对象 | 包含Ref对象的普通对象 |
| 访问方式 | .value | 直接访问 | .value | .value |
| 保持连接 | - | - | 与源属性同步 | 与所有源属性同步 |
| 主要用途 | 创建响应式数据 | 创建响应式对象 | 提取单个属性为ref | 解构响应式对象 |
使用场景建议
javascript
// 场景1:基本类型用ref
const count = ref(0)
const loading = ref(false)
// 场景2:相关数据组用reactive
const form = reactive({
username: '',
password: '',
remember: false
})
// 场景3:组合式函数返回用toRefs
function useUser() {
const state = reactive({
name: '',
age: 0,
isLoading: false
})
// ...逻辑代码
return toRefs(state) // 方便使用者解构
}
// 场景4:解构props用toRef
const props = defineProps(['title', 'visible'])
const title = toRef(props, 'title')
const visible = toRef(props, 'visible')
// 或者一次性转换
const { title, visible } = toRefs(props)注意事项
ref vs reactive:
- 基本类型用
ref - 相关数据组用
reactive - 大型项目推荐统一使用
ref(更一致)
- 基本类型用
解构问题:
- 直接解构
reactive对象会失去响应性 - 使用
toRefs解构可保持响应性
- 直接解构
响应式丢失:
javascript// 错误:直接赋值会丢失响应性 let { x, y } = reactive({ x: 1, y: 2 }) // 正确:使用toRefs let { x, y } = toRefs(reactive({ x: 1, y: 2 }))
这些API提供了灵活的响应式数据处理方式,根据具体场景选择合适的工具可以编写出更清晰、更易维护的代码。
