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 相关文章推荐
vue3.0实现点击切换验证码(组件)及校验
Nov 18 Vue.js
浅析VUE防抖与节流
Nov 24 Vue.js
Vue3+elementui plus创建项目的方法
Dec 01 Vue.js
vue3.0中友好使用antdv示例详解
Jan 05 Vue.js
手动实现vue2.0的双向数据绑定原理详解
Feb 06 Vue.js
解读Vue组件注册方式
May 15 Vue.js
Vue中foreach数组与js中遍历数组的写法说明
Jun 05 Vue.js
vue实现可以快进后退的跑马灯组件
Apr 08 Vue.js
vue实现列表垂直无缝滚动
Apr 08 Vue.js
vue 自定义的组件绑定点击事件
Apr 21 Vue.js
vue使用element-ui按需引入
May 20 Vue.js
Vue深入理解插槽slot的使用
Aug 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
德生PL450的电路分析和低放电路的改进办法
2021/03/02 无线电
PHP has encountered an Access Violation 错误的解决方法
2010/01/17 PHP
php函数serialize()与unserialize()用法实例
2014/11/06 PHP
phpcms手机内容页面添加上一篇和下一篇
2015/06/05 PHP
php对二维数组进行相关操作(排序、转换、去空白等)
2015/11/04 PHP
隐藏Nginx或Apache以及PHP的版本号的方法
2016/01/03 PHP
thinkphp验证码的实现(form、ajax实现验证)
2016/07/28 PHP
CL vs ForZe BO5 第二场 2.13
2021/03/10 DOTA
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
jquery ui resize 中border-box的bug修正
2015/04/26 Javascript
jQuery弹出层插件popShow(改进版)用法示例
2017/01/23 Javascript
基于vue实现图片验证码倒计时60s功能
2019/12/10 Javascript
Vue解决移动端弹窗滚动穿透问题
2020/12/15 Vue.js
vue使用过滤器格式化日期
2021/01/20 Vue.js
Python的time模块中的常用方法整理
2015/06/18 Python
独特的python循环语句
2016/11/20 Python
python中的decorator的作用详解
2018/07/26 Python
Python正则匹配判断手机号是否合法的方法
2020/12/09 Python
python网络应用开发知识点浅析
2019/05/28 Python
12个步骤教你理解Python装饰器
2019/07/01 Python
python3.7 的新特性详解
2019/07/25 Python
Python 矩阵转置的几种方法小结
2019/12/02 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
2020/03/12 Python
python进行参数传递的方法
2020/05/12 Python
Python猫眼电影最近上映的电影票房信息
2020/09/18 Python
详解Python Celery和RabbitMQ实战教程
2021/01/20 Python
pycharm 实现光标快速移动到括号外或行尾的操作
2021/02/05 Python
css3动画过渡实现鼠标跟随导航效果
2018/02/08 HTML / CSS
日本网路线上商品代购服务:转送JAPAN
2016/08/05 全球购物
荷兰网上鞋店:Ziengs.nl
2017/01/02 全球购物
草莓网化妆品日本站:Strawberrynet日本
2017/10/20 全球购物
Zavvi荷兰:英国大型音像制品和图书游戏零售商
2018/03/22 全球购物
暑期实践思想汇报
2014/01/06 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
班级课外活动总结
2014/07/09 职场文书
2016年保险公众宣传日活动总结
2016/04/05 职场文书