Skip to content

响应式

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> ✅ 不需要 .value

2. 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)

注意事项

  1. ref vs reactive

    • 基本类型用ref
    • 相关数据组用reactive
    • 大型项目推荐统一使用ref(更一致)
  2. 解构问题

    • 直接解构reactive对象会失去响应性
    • 使用toRefs解构可保持响应性
  3. 响应式丢失

    javascript
    // 错误:直接赋值会丢失响应性
    let { x, y } = reactive({ x: 1, y: 2 })
    
    // 正确:使用toRefs
    let { x, y } = toRefs(reactive({ x: 1, y: 2 }))

这些API提供了灵活的响应式数据处理方式,根据具体场景选择合适的工具可以编写出更清晰、更易维护的代码。