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


Posted in Vue.js onFebruary 18, 2022

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

一、基础

1.ref

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

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

<script>
import { ref } from 'vue'
export default {
 setup() {
  const ageRef = ref(20)

  setInterval(() => {
   ageRef.value += 1
  }, 1000)
  
  return {
   ageRef
  }
 },
}
</script>

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

(2) 可用于reactive中

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

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

<script>
import { ref, reactive } from 'vue'
export default {
 setup() {
  const ageRef = ref(20)
  const info = reactive({
   age: ageRef
  })
  setInterval(() => {
   ageRef.value += 1
  }, 1000)
  
  return {
   info
  }
 },
}
</script>

(3) 可用于获取Dom

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

<script>
import { ref, onMounted } from 'vue'
export default {
 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,具有响应式
  • 两者保持引用关系

我们来看下面这段代码

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

<script>
import { toRef, reactive } from 'vue'
export default {
 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
  • 两者保持引用关系

我们来看下面这段代码

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

<script>
import { reactive, toRefs } from 'vue'
export default {
 setup() {
  const state = reactive({
   name: 'JL',
   age: 18
  })

  const stateRefs = toRefs(state)

  setTimeout(() => {
   state.age = 20
  }, 1000)

  setTimeout(() => {
   stateRefs.age.value = 21
  }, 2000)

  return stateRefs
 },
}
</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

例如:

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

<script>
import { reactive, toRefs } from 'vue'
export default {
 setup() {
  function test() {
   const state = reactive({
    x: 1,
    y: 2
   })
   return toRefs(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

  • 初衷: 在不丢失响应式的前提下,对对象数据进行解构
  • 前提: 针对的是响应式对象,不是普通对象
  • 结果: 不创造响应式,只延续响应式

到此这篇关于Vue3如何理解ref toRef和toRefs的区别的文章就介绍到这了,更多相关Vue3 ref toRef和toRefs内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
在vue中通过render函数给子组件设置ref操作
Nov 17 Vue.js
vue3.0中setup使用(两种用法)
Dec 02 Vue.js
基于vue+echarts数据可视化大屏展示的实现
Dec 25 Vue.js
vue登录页实现使用cookie记住7天密码功能的方法
Feb 18 Vue.js
vue完美实现el-table列宽自适应
May 08 Vue.js
SSM VUE Axios详解
Oct 05 Vue.js
VUE之图片Base64编码使用ElementUI组件上传
Apr 09 Vue.js
vue报错function () { [native code] },无法出现我们想要的内容 Unknown custom element
Apr 11 Vue.js
如何优化vue打包文件过大
Apr 13 Vue.js
vue动态绑定style样式
Apr 20 Vue.js
vue @ ~ 相对路径 路径别名设置方式
Jun 05 Vue.js
Vue Mint UI mt-swipe的使用方式
Jun 05 Vue.js
Vue h函数的使用详解
Feb 18 #Vue.js
详解Vue中$props、$attrs和$listeners的使用方法
Feb 18 #Vue.js
前端vue+express实现文件的上传下载示例
一篇文章告诉你如何实现Vue前端分页和后端分页
vue项目中的支付功能实现(微信支付和支付宝支付)
Feb 18 #Vue.js
vue3获取当前路由地址
Feb 18 #Vue.js
Vue elementUI表单嵌套表格并对每行进行校验详解
Feb 18 #Vue.js
You might like
使用无限生命期Session的方法
2006/10/09 PHP
有关PHP性能优化的介绍
2013/06/20 PHP
linux下php上传文件注意事项
2016/06/11 PHP
PHP封装mysqli基于面向对象的mysql数据库操作类与用法示例
2019/02/25 PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
2020/02/18 PHP
ExtJS 工具栏 分页事件参数
2010/03/05 Javascript
jquery 的 $(&quot;#id&quot;).html() 无内容的解决方法
2010/06/07 Javascript
json原理分析及实例介绍
2012/11/29 Javascript
jquery实现简单Tab切换菜单效果
2020/07/17 Javascript
JS访问DOM节点方法详解
2016/11/29 Javascript
js实现前端图片上传即时预览功能
2017/08/02 Javascript
JavaScript面向对象精要(上部)
2017/09/12 Javascript
Angular 开发学习之Angular CLI的安装使用
2017/12/31 Javascript
angular第三方包开发整理(小结)
2018/04/19 Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
2019/09/29 Javascript
js函数柯里化的方法和作用实例分析
2020/04/11 Javascript
[03:56]显微镜下的DOTA2第十一期——鬼畜的死亡先知播音员
2014/06/23 DOTA
Django小白教程之Django用户注册与登录
2016/04/22 Python
python2.7到3.x迁移指南
2018/02/01 Python
Pytorch Tensor的统计属性实例讲解
2019/12/30 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
200行python代码实现贪吃蛇游戏
2020/04/24 Python
Python判断变量是否是None写法代码实例
2020/10/09 Python
css3进行截取替代js的substring
2013/09/02 HTML / CSS
phonegap常用事件总结(必看篇)
2017/03/31 HTML / CSS
美国第二大连锁书店:Books-A-Million
2017/12/28 全球购物
荷兰天然和有机产品网上商城:BigGreenSmile.nl
2020/07/26 全球购物
美国最大最全的亚洲购物网站:美国亚米网(Yamibuy)
2020/05/05 全球购物
高三自我鉴定范文
2013/10/19 职场文书
房地产销售大学生自我评价分享
2013/11/11 职场文书
大学生在校表现评语
2014/12/31 职场文书
庆七一活动简报
2015/07/20 职场文书
2015初中团支部工作总结
2015/07/21 职场文书
利用Java设置Word文本框中的文字旋转方向的实现方法
2021/06/28 Java/Android
关于使用Redisson订阅数问题
2022/01/18 Redis
使用ICOM IC-R9500接收机同时测评十台收音机中波接收性能
2022/05/10 无线电