Vue3如何理解ref toRef和toRefs的区别

目录
  • 一、基础
    • 1.ref
    • 2.toRef
  • 3.toRefs
  • 4.最佳的使用方式
  • 二、深入
    • 1.为什么需要ref
    • 2.ref为什么需要.value
    • 3.为什么需要toRef和toRefs

Vue3中新增了几种创建响应式数据的方法,其各自的作用当然也不尽相同,每一种方法都有其自己的应用场景,今天我们来聊聊什么是ref toRef和toRefs?三者在使用方式上有什么不同?最佳的使用方式是什么?

一、基础

1.ref

(1) 生成值类型的响应式数据, 通过 .value修改值

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<template>

 <div>{{ ageRef }}</div>

</template>

<script>

import { ref } from'vue'

exportdefault{

 setup() {

  const ageRef = ref(20)

  setInterval(() => {

   ageRef.value += 1

  }, 1000)

   

  return{

   ageRef

  }

 },

}

</script>

上面这段代码,定义了一个ageRef变量,并每秒将ageRef加1,页面展示的数值也会加1.

(2) 可用于reactive中

将上面的代码改动如下, 引入reactive定义变量,将ref定义的变量引入reactive中, 模板中展示reactive的变量. 最后的效果和上面(1)的一样

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<template>

 <div>{{ info.age }}</div>

</template>

<script>

import { ref, reactive } from'vue'

exportdefault{

 setup() {

  const ageRef = ref(20)

  const info = reactive({

   age: ageRef

  })

  setInterval(() => {

   ageRef.value += 1

  }, 1000)

   

  return{

   info

  }

 },

}

</script>

(3) 可用于获取Dom

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<template>

 <div ref="eleDom">ref-dom-test</div>

</template>

<script>

import { ref, onMounted } from'vue'

exportdefault{

 setup() {

  const eleDom = ref(null)

  onMounted(() => {

   console.log(eleDom.value.innerHTML)// ref-dom-test

  })

  return{

   eleDom

  }

 },

}

上面代码控制台输出ref-dom-test, 说明获取到了Dom元素.
要获取Dom元素必须要符合以下规则

定义的ref变量名必须要和模板中ref中的值一致,如代码中的eleDom

2.toRef

  • 针对一个响应式对象的prop
  • 创建一个ref,具有响应式
  • 两者保持引用关系

我们来看下面这段代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<template>

 <div>{{ state.age }} --- {{ ageRef }}</div>

</template>

<script>

import { toRef, reactive } from'vue'

exportdefault{

 setup() {

  const state = reactive({

   name:'JL',

   age: 18

  })

  const ageRef = toRef(state,'age')

  setTimeout(() => {

   state.age = 20

  }, 1000)

   

  setTimeout(() => {

   ageRef.value = 21

  }, 2000)

   

  return{

   state,

   ageRef

  }

 },

}

</script>

上面的代码中,使用toRef将state的age属性变成一个响应式变量,然后在1秒后将state的age值变为20,此时ageRef也会变成20;在2秒后将ageRef的值变为21,此时state的age值也会变成21,说明了两者保持相互引用关系

toRef针对的是响应式,针对的不是普通对象,如果用于非响应式,产出的结果不具有响应式

3.toRefs

  • 将一个响应式对象转为普通对象
  • 对象的每一个属性都是对应的ref
  • 两者保持引用关系

我们来看下面这段代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<template>

 <div>{{ name }}---{{ age }}</div>

</template>

<script>

import { reactive, toRefs } from'vue'

exportdefault{

 setup() {

  const state = reactive({

   name:'JL',

   age: 18

  })

  const stateRefs = toRefs(state)

  setTimeout(() => {

   state.age = 20

  }, 1000)

  setTimeout(() => {

   stateRefs.age.value = 21

  }, 2000)

  returnstateRefs

 },

}

</script>

上面的代码中,使用toRefs将state转变成一个普通对象,这时候就可以直接返回stateRefs,这时候在template就可以直接调用name和age。然后在1秒后将state的age值变为20,此时页面中的age也会变成20;在2秒后将stateRefs中的name的值变为21,此时页面中的age值也会变成21,说明了两者保持相互引用关系

toRefs将响应式对象变成普通对象后,每一个属性都具有响应式ref,此时需要使用 .value才能获取其值

4.最佳的使用方式

  • reactive做对象的响应式,ref做值类型响应式
  • setup中返回toRefs(state), 或者toRef(state, 'xxx')---(这样就能够在template中不使用state.xxx)
  • ref的变量命名都用xxxRef
  • 合成函数返回响应式对象时,使用toRefs

例如:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<template>

 <div>x:{{x}} y:{{y}}</div>

</template>

<script>

import { reactive, toRefs } from'vue'

exportdefault{

 setup() {

  functiontest() {

   const state = reactive({

    x: 1,

    y: 2

   })

   returntoRefs(state)

  }

  const {x, y} = test()

  setTimeout(() => {

   x.value = 2

  }, 1000)

  return{

   x,

   y

  }

 }

}

</script>

上面的代码,test函数中定义了响应式对象state,并通过toRefs将其转为普通对象并返回,这时候可以结构赋值,并且值是响应式的

二、深入

1.为什么需要ref

在上面我们讲到,使用reactive和toRef也可以将值类型转换成响应式的,为什么还需要ref呢?

  • 值类型不具有响应式(proxy)
  • setup()、computed()...都可能返回值类型,如果vue不定义ref,用户需要响应式的值类型的时候就会通过其他方式(reactive/toRef, reactive/toRefs)自造ref,就会造成代码更混乱

2.ref为什么需要.value

ref为什么需要加一个.value来获取值呢?为什么要这么麻烦呢?

  • ref是一个对象(不会丢失响应式),value存储值
  • 通过.value属性的get和set来实现响应式
  • 用于reactive和模板(vue编译)的时候不需要.value,其他情况都需要

3.为什么需要toRef和toRefs

  • 初衷: 在不丢失响应式的前提下,对对象数据进行解构
  • 前提: 针对的是响应式对象,不是普通对象
  • 结果: 不创造响应式,只延续响应式
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六边形学者自由子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值