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 表单输入框不支持focus及blur事件的解决方案
Nov 17 Vue.js
Vue用mixin合并重复代码的实现
Nov 27 Vue.js
vue实现简易的双向数据绑定
Dec 29 Vue.js
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 Vue.js
vue3中轻松实现switch功能组件的全过程
Jan 07 Vue.js
Vue通过懒加载提升页面响应速度
May 10 Vue.js
详细聊聊vue中组件的props属性
Nov 02 Vue.js
vue使用echarts实现折线图
Mar 21 Vue.js
vue如何使用模拟的json数据查看效果
Mar 31 Vue.js
vue 数字翻牌器动态加载数据
Apr 20 Vue.js
解决vue自定义组件@click点击失效问题
Apr 30 Vue.js
Vue ECharts实现机舱座位选择展示功能
May 15 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
截获网站title标签之家内容的例子
2006/10/09 PHP
php防止恶意刷新与刷票的方法
2014/11/21 PHP
CI框架常用函数封装实例
2016/11/21 PHP
PHP从零开始打造自己的MVC框架之类的自动加载实现方法详解
2019/06/03 PHP
提高 DHTML 页面性能
2006/12/25 Javascript
Riot.js 快速的JavaScript单元测试框架
2009/11/09 Javascript
JavaScript的public、private和privileged模式
2009/12/28 Javascript
JavaScript的parseInt 取整使用
2011/05/09 Javascript
基于SVG的web页面图形绘制API介绍及编程演示
2013/06/28 Javascript
jquery图片不完全按比例自动缩小的简单代码
2013/07/29 Javascript
JQuery设置文本框和密码框得到焦点时的样式
2013/08/30 Javascript
js中键盘事件实例简析
2015/01/10 Javascript
js使用DOM操作实现简单留言板的方法
2015/04/10 Javascript
PageSwitch插件实现100种不同图片切换效果
2015/07/28 Javascript
js实现带圆角的两级导航菜单效果代码
2015/08/24 Javascript
jquery日历插件datepicker用法分析
2016/01/22 Javascript
详解JS中的attribute属性
2017/04/25 Javascript
AngularJS基于factory创建自定义服务的方法详解
2017/05/25 Javascript
如何理解Vue的.sync修饰符的使用
2017/08/17 Javascript
使用Bootrap和Vue实现仿百度搜索功能
2017/10/26 Javascript
jQuery除指定区域外点击任何地方隐藏DIV功能
2017/11/13 jQuery
AngularJS使用$http配置对象方式与服务端交互方法
2018/08/13 Javascript
javascript匿名函数中的'return function()'作用
2018/10/15 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
js实现登录时记住密码的方法分析
2020/04/05 Javascript
[33:15]2018DOTA2亚洲邀请赛3月30日 小组赛B组 VP VS Mineski
2018/03/31 DOTA
[02:23]2018DOTA2亚洲邀请赛趣味视频——反应测试
2018/04/04 DOTA
Python可变参数用法实例分析
2017/04/02 Python
python、java等哪一门编程语言适合人工智能?
2017/11/13 Python
Pandas实现DataFrame按行求百分数(比例数)
2019/12/27 Python
python批量替换文件名中的共同字符实例
2020/03/05 Python
python的setattr函数实例用法
2020/12/16 Python
IE10 Error.stack 让脚本调试更加方便快捷
2013/04/22 HTML / CSS
医药大学生求职简历的自我评价
2013/10/17 职场文书
我为自己代言广告词
2014/03/18 职场文书
经济贸易系毕业生求职信
2014/05/31 职场文书