vue3的ref和reactive以及toRef和toRefs的区别

36 阅读3分钟

只有响应式数据能更新界面ref()、reactive()可以生成响应式数据。
ref一般用于基础数据类型,按值传递reactive用于复杂数据类型,按引用传递toRef/toRefs一般用于解构响应式数据,因为如果直接解构响应式数据会使其失去响应性
toRef返回的值是否具有响应性取决于被解构的对象本身是否具有响应性。响应式数据经过toRef返回的值仍具有响应性,非响应式数据经过toRef返回的值仍没有响应性。toRef返回的是Ref<T>类型,因此在setup()内需要使用.value赋值或调用
toRefs相当于对对象内每个属性调用toReftoRefs返回的对象内的属性使用时需要加.value

一、ref能定义任何类型的响应式数据,

1、但是使用的时候需要通过.value的形式去修改。
2、参数可以传入任意数据类型。
3、vue 3.0 setup里定义数据时推荐优先使用ref,方便逻辑拆分和业务解耦。

import { ref } from 'vue'
// 为基本数据类型添加响应式状态
const name = ref('Neo')
// 为复杂数据类型添加响应式状态
const state = ref({
  count: 0
})
// 打印name的值
console.log(name.value)
// 打印count的值
console.log(state.value.count)

return {
   name,
   state
}
二、reactive定义的是对象类型的响应式数据。

1、直接添加了响应式可以直接使用,不用.value
2、参数只能传入对象类型.
3、不能通过 ...state方式解构,这样会丢失响应式。

import { reactive, toRefs } from 'vue'

// 响应式状态
const state = reactive({
  count: 0
})

// 打印count的值
console.log(state.count)

return {
    ...toRefs(state)
}

注意reactive封装的响应式对象,不要通过解构的方式return,这是不具有响应式的。可以通过 toRefs 处理,然后再解构返回,这样才具有响应式

三、toRef

针对一个响应式对象(reactive 封装)prop(属性)创建一个ref,且保持响应式
两者 保持引用关系

1、接收两个参数:源响应式对象和属性名,返回一个ref数据。
例如使用父组件传递的props数据时,要引用props的某个属性且要保持响应式连接时就很有用。

2、获取数据值的时候需要加.value
toRef后的ref数据如果是复杂类型数据时,不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据。

import { defineComponent, toRef } from 'vue'
export default defineComponent({
props: [title],
setup (props) {
  // 创建变量myTitle
  const myTitle = toRef(props, 'title')
  console.log(myTitle.value)
}
})
四、toRefs

toRefs 是一种用于破坏响应式对象并将其所有属性转换为ref 的实用方法
将响应式对象(reactive封装)转成普通对象
对象的每个属性(Prop)都是对应的ref
两者保持引用关系
用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref

1、常用于es6的解构赋值操作,因为在对一个响应式对象直接解构时解构后的数据将不再有响应式,而使用toRefs可以方便解决这一问题。
2、获取数据值的时候需要加value
toRefs后的ref数据如果是复杂类型数据时,不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
作用其实和 toRef类似,只不过toRef 是对一个个属性手动赋值,而 toRefs 是自动解构赋值。

import { defineComponent, toRefs } from 'vue'
export default defineComponent({
  props: [title],
  setup (props) {
    // 使用了解构赋值语法创建了变量myTitle
    const { myTitle } = toRefs(props)
    console.log(myTitle.value)
  }
})

vue3中,可以直接使用reftoRefs来定义数据。