reactive、ref、toRef、toRefs

reactive和ref

1.reactive

接收的数据类型:对象类型

使用:

const data1 = reactive({
  value: "1",
  name: "2"
})
data1.value // 使用

结果:reactive、ref、toRef、toRefs_第1张图片

作用:把参数加工成一个代理对象(proxy对象)

原理:基于Es6的Proxy实现,通过代理操作源对象,相比于ref定义的浅层次响应式数据对象,reactive定义的是更深层次的响应式数据对象。

const data1 = reactive({
  value: "1",
  name: {
    value: "2" // 响应式的
  }
})

缺点:如果使用解构赋值解构对象,解构出来的结果就不是响应式了。必须要解构的话可以使用toRefs将reactive定义的对象中的属性都转为响应式的再进行解构。

const position = reactive({ x, y })

const {x, y} = position // 这样定义的x,y不是响应式

const {x, y} = toRefs(position)  // 这样定义的x,y是响应式

2.ref

接收的数据类型:基本数据类型、对象类型

使用ref转换基本数据类型:

const data3 = ref(1)

data3.value 取值方法

结果:

reactive、ref、toRef、toRefs_第2张图片

ref转换基本数据类型的原理是创建一个具有value属性的对象,并使用Object.defineProperty()将其定义为响应式对象。所以ref定义的响应式对象需要从.value属性中取值。但是在模板中编译器会自己根据响应式对象的类型判断是否需要从value中取值,不需要手动加.value。

使用ref将对象转为响应式对象:

const data2 = ref({
  value: "1",
  name: "2"
})
console.log("ref", data2)

结果:其本身是一个RefImpl,但是其value是一个Proxy,因为如果ref接收的参数是对象类型,会把对象参数通过reactive函数加工成一个Proxy代理对象放到ref的value属性上。可以在下图中看到value属性是一个Proxy对象。与直接使用reactive不同的是,需要从value中取值,不能直接取值。reactive、ref、toRef、toRefs_第3张图片

reactive和ref的区别:

  • 接收的数据类型不同:ref可以接收基本数据类型和对象,reactive方法只能接受对象
  • 用法不同:ref需要在.value属性上取值,reactive可以直接使用  对象.键名  的方式取值
  • 原理不同:ref使用Object.defineProperty()的get和set方法,而reactive的响应式原理是依赖于ES6中的Proxy()

toRef和toRefs

toRef和toRefs是将响应式对象中的属性也转换为响应式的。区别在于toRef一次只能转换一个属性,toRefs是一次将所有属性都转为响应式的。

需要注意的是:toRef和toRefs与ref的区别是:ref的本质是拷贝,改变结果数据的值不会改变源对象的值,而toRef后的ref数据如果是复杂类型数据时,不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据。

ref数据发生改变,界面会自动更新;toRef当数据发生改变是,界面不会自动更新。

3.toRef 

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

    const myTitle = toRef(props, 'title')

    console.log(myTitle.value)

4.toRefs

作用:toRefs 用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref对象。常用于es6的解构赋值操作,因为在对一个响应式对象直接解构时解构后的数据将不再有响应式,而使用toRefs可以方便解决这一问题。

工作原理:会遍历代理对象的所有属性,并将所有属性转换为响应式对象并挂载在一个新对象上返回。获取数据值的时候需要加.value。

const { myTitle } = toRefs(props)
console.log(myTitle.value)

你可能感兴趣的:(前端)