0


谈谈Vue3中的ref和reactive

一、是什么?

ref和reactive是Vue3中用来实现数据响应式的API
一般情况下,

ref

定义基本数据类型,

reactive

定义引用数据类型
(我喜欢用它来定义对象,不用它定义数组,原因后面讲)
我理解的ref本质上是reactive的再封装

二、先聊reactive

reactive定义引用数据类型(以对象和数组举例),它能够将复杂数据类型的内部属性或者数据项声明为响应式数据,所以reactive的响应式是深层次的,其底层是通过ES6的

Proxy

来实现数据响应式,相对于Vue2的

Object.defineProperty

,具有能监听增删操作,能监听对象属性的变化等优点

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

const paginationConfig =reactive({pageNum:1,pageSize:10})// 定义constonChange=()=>{
    paginationConfig.pageNum =2// js使用
    paginationConfig.pageSize =20// js使用}
<!-- Vue3模板引用使用 --><a-paginationv-model:current="paginationConfig.pageNum"></a-pagination>

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

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

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

三、再聊ref

为什么我会理解成ref是reactive的再封装,因为在ref的底层源码里最终还是reactive()来实现的
在这里插入图片描述
在这里插入图片描述
由源码分析得知,如果是对象类型,底层走的还是reactive()的逻辑,另外我们知道,使用ref定义基本数据类型时,在脚本里使用时,需要加

.value

后缀,然而在模板里不需要,这是因为Vue3会自动帮你加上,这就使得ref相比reactive更加简单

let num =ref(0)// 定义let isShow =ref(false)// 定义constonChange=()=>{
    num.value++// js使用
    isShow.value =true// js使用}
<!-- Vue3模板引用使用 --><a-modalv-model:visible="isShow"></a-modal>

四、ref和reactive定义数组对比

使用ref定义数组举例如下

const tableData =ref([])// 定义constgetTableData=async()=>{const{ data }=awaitgetTableDataApi()// 模拟接口获取表格数据
    tableData.value = data // 修改}
<!-- Vue3模板引用使用 --><a-tablev-model:dataSource="tableData"></a-table>

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

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

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

// 方法一:改为 ref 定义const tableData =ref([])constgetTableData=async()=>{const{ data }=awaitgetTableDataApi()
    tableData.value = data // 使用.value重新赋值}// 方法二:使用 push 方法const tableData =reactive([])constgetTableData=async()=>{const{ data }=awaitgetTableDataApi()
    tableData.push(...data)// 先使用...将data解构,再使用push方法}// 方法三:定义时数组外层嵌套一个对象const tableData =reactive({list:[]})constgetTableData=async()=>{const{ data }=awaitgetTableDataApi()
    tableData.list = data // 通过访问list属性重新赋值}// 方法四:赋值前再包一层 reactiveconst tableData =reactive([])constgetTableData=async()=>{const{ data }=awaitgetTableDataApi()
    tableData =reactive(data)// 赋值前再包一层reactive}

五、对比总结

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

本文转载自: https://blog.csdn.net/poppingJ/article/details/125429506
版权归原作者 前端小七 所有, 如有侵权,请联系我们删除。

“谈谈Vue3中的ref和reactive”的评论:

还没有评论