经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » React » 查看文章
简单谈谈Vue3中的ref和reactive
来源:jb51  时间:2023/4/17 9:15:43  对本文有异议

一、是什么?

ref和reactive是Vue3中用来实现数据响应式的API

一般情况下,ref定义基本数据类型,reactive定义引用数据类型

(我喜欢用它来定义对象,不用它定义数组,原因后面讲)

我理解的ref本质上是reactive的再封装

二、先聊reactive

reactive定义引用数据类型(以对象和数组举例),它能够将复杂数据类型的内部属性或者数据项声明为响应式数据,所以reactive的响应式是深层次的,其底层是通过ES6的Proxy来实现数据响应式,相对于Vue2的Object.defineProperty,具有能监听增删操作,能监听对象属性的变化等优点

使用reactive定义对象数据类型举例

  1. const paginationConfig = reactive({
  2. pageNum: 1,
  3. pageSize: 10
  4. }) // 定义
  5.  
  6. const onChange = () => {
  7. paginationConfig.pageNum = 2 // js使用
  8. paginationConfig.pageSize = 20 // js使用
  9. }
  1. <!-- Vue3模板引用使用 -->
  2. <a-pagination v-model:current="paginationConfig.pageNum"></a-pagination>

若用reactive定义基本数据类型,Vue3会报警告错误,如图

  1. const str = reactive('我是字符串')

控制台报错

源码解析

分析Vue3源码可知,使用reactive定义响应式数据时,若数据不是对象类型直接就返回了,就不会进行后续的数据响应式处理了,这也就是我只用reactive定义对象型响应式数据的原因,那数组类型数据怎么办呢?答案在下文中可以找到

三、再聊ref

为什么我会理解成ref是reactive的再封装,因为在ref的底层源码里最终还是reactive()来实现的

由源码分析得知,如果是对象类型,底层走的还是reactive()的逻辑,另外我们知道,使用ref定义基本数据类型时,在脚本里使用时,需要加.value后缀,然而在模板里不需要,这是因为Vue3会自动帮你加上,这就使得ref相比reactive更加简单

  1. let num = ref(0) // 定义
  2. let isShow = ref(false) // 定义
  3.  
  4. const onChange = () => {
  5. num.value++ // js使用
  6. isShow.value = true // js使用
  7. }
  1. <!-- Vue3模板引用使用 -->
  2. <a-modal v-model:visible="isShow"></a-modal>

四、ref和reactive定义数组对比

使用ref定义数组举例如下

  1. const tableData = ref([]) // 定义
  2.  
  3. const getTableData = async () => {
  4. const { data } = await getTableDataApi() // 模拟接口获取表格数据
  5. tableData.value = data // 修改
  6. }
  1. <!-- Vue3模板引用使用 -->
  2. <a-table v-model:dataSource="tableData"></a-table>

图中以我们常用的表格数据举例,可以看到,ref定义数组与定义基本数据类型没什么差别,接下来看看reactive

  1. const tableData = reactive([]) // 定义
  2.  
  3. const getTableData = async () => {
  4. const { data } = await getTableDataApi() // 模拟接口获取表格数据
  5. tableData = data // 修改,错误示例,这样赋值会使tableData失去响应式
  6. }
  1. <!-- Vue3模板引用使用 -->
  2. <a-table v-model:dataSource="tableData"></a-table>

需要注意的是,使用 tableData = data 的修改方式会造成 tableData 响应式丢失,解决方法如下(供参考)

  1. // 方法一:改为 ref 定义
  2. const tableData = ref([])
  3. const getTableData = async () => {
  4. const { data } = await getTableDataApi()
  5. tableData.value = data // 使用.value重新赋值
  6. }
  7. // 方法二:使用 push 方法
  8. const tableData = reactive([])
  9. const getTableData = async () => {
  10. const { data } = await getTableDataApi()
  11. tableData.push(...data) // 先使用...将data解构,再使用push方法
  12. }
  13. // 方法三:定义时数组外层嵌套一个对象
  14. const tableData = reactive({ list:[] })
  15. const getTableData = async () => {
  16. const { data } = await getTableDataApi()
  17. tableData.list = data // 通过访问list属性重新赋值
  18. }
  19. // 方法四:赋值前再包一层 reactive
  20. const tableData = reactive([])
  21. const getTableData = async () => {
  22. const { data } = await getTableDataApi()
  23. tableData = reactive(data) // 赋值前再包一层reactive
  24. }

五、对比总结

  1. ref用于定义基本类型和引用类型,reactive仅用于定义引用类型
  2. reactive只能用于定义引用数据类型的原因在于内部是通过ES6的Proxy实现响应式的,而Proxy不适用于基本数据类型
  3. ref定义对象时,底层会通过reactive转换成具有深层次的响应式对象,所以ref本质上是reactive的再封装
  4. 在脚本里使用ref定义的数据时,记得加.value后缀
  5. 在定义数组时,建议使用ref,从而可避免reactive定义时值修改导致的响应式丢失问题

总结

到此这篇关于简单谈谈Vue3中ref和reactive的文章就介绍到这了,更多相关Vue3中ref和reactive内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号