避大坑!Vue3中reactive丢失响应式的问题

在vue3中,我们定义响应式数据无非是ref和reactive。
但是有的小伙伴会踩雷!导致定义的响应式丢失的问题。

reactive丢失响应式的情况1(直接赋值)

javascript 复制代码
`场景:
1.你定义了一个数据:let data=reactive({
          name:"",
          age:""
})
2.然后你请求了接口,赋值给data
let res=await getUserApi();  //请求接口
data=res.data;                     //将返回的结果赋值给data`

大错特错!!!

reactive丢失响应式的情况2(解构赋值)

javascript 复制代码
`场景:
1.你定义了一个数据:let data=reactive({
          name:"",
          age:""
})
2.然后你解构了
let {name}=data; //解构赋值`

大错特错!!!

了解响应式

1.ref 定义数据(包括对象)时,都会变成 RefImpl(Ref 引用对象) 类的实例,无论是修改还是重新赋值都会调用 setter,都会经过 reactive 方法处理为响应式对象。

2.但是 reactive 定义数据(必须是对象),是直接调用 reactive 方法处理成响应式对象。如果重新赋值,就会丢失原来响应式对象的引用地址,变成一个新的引用地址,这个新的引用地址指向的对象是没有经过 reactive 方法处理的,所以是一个普通对象,而不是响应式对象。解构同理。

避坑办法:

  1. 避开直接赋值和结构,reactive直接包裹一个对象。
javascript 复制代码
`let data=reactive({
    userData:{}        //里面定义一个对象,这样赋值就不会丢失响应式了。
})

//获取接口数据
let res=await getUserApi();  //请求接口
data.userData=res.data;      //将返回的结果赋值给data`
  1. 简单数据类型使用ref()来进行定义。

拔高:TS对reactive里对象进行限制

上面那种情况是没在TS限制的情况下我们解决的,但是有TS用户就有疑问了,这样我在reactive内部再定义一个对象,就失去了对userData的类型限制了,怎么办呢?

答案:写类!!!!!!!!!!!!!!!!!!!

下面我们就来研究一下:

1.我们最开始会可能这样对data加上类型限制:

javascript 复制代码
`interface dataRule{
    name:string,
    age:number
}

//定义数据
let data:dataRule=reactive({
    name:"",
    age:""
})

//但是,当获取接口的时候
let res=await getUserApi();  //请求接口
//data=res.data;              //我们已经知道不能这样写了,会丢失响应式。(xxx达咩)
//2.这时聪明的你可能会这样
data.name=res.data.name;
data.age=res.data.age;


//PS:
//问题一:赋值太麻烦
//这样确实可以不损坏响应式,但是如果我说你这里面不仅仅有name和age呢,而是有很多很多,那咋办?

//问题二:无法对userData做类型限制
//你可能又想这样:
let data=reactive({
     userData:{}  
})
这样写,我们怎么能对userData做类型限制呢?`

实现:分开写类!!!!!!!!!!!(重点来啦)

1.单独拿出来一个ts文件,比如user.ts

javascript 复制代码
`//1.定义限制userData的接口
export interface dataRule{
    name:string,
    age:number
}

//写类
export class data{
    //定义userData并且做TS限制和赋初始值
    userData:dataRule={
        name:"",
        age:""
    }
}`

在对应的.vue文件中引入该类。

javascript 复制代码
`//1.引入刚写好ts类文件
import {dataRule,data} from "@/type/user.ts"

//2.重点来了,我实例化出来data,然后用一个变量User接收。
let User=reactive(new data());

/*
//实例化出来以后相当于这样的结构:
User={
    userData:{
        name:"",
        age:""
    }
}
*/


//3.我们调用接口
//获取接口数据
let res=await getUserApi();  //请求接口
User.userData=res.data;      //将返回的结果赋值给data,这样也不会丢失响应式,并且userData也受了TS的限制。`

结语:

在前端的道路上,我们就是要不断地保持学习,然后逐渐的变强大,沉淀自己,我们顶峰相见。

--Yan

相关推荐
程序猿DD3 小时前
OctaFuse Gateway 2.11.0:流式请求优化、用户折扣策略与错误契约升级
前端·后端
尾善爱看海3 小时前
《JavaScript 数组操作全攻略:12 类 API + 30 个实战场景 + 20 个避坑指南》
前端·javascript·面试
计算机毕设定制辅导-无忧学长4 小时前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台
计算机魔术师4 小时前
Anthropic 估值冲 4 万亿,但企业客户已经偷偷换了便宜模型
前端
OpsEye4 小时前
为什么你的 Agent 莫名烧钱?聊聊循环调用的兜底方案
javascript·ai编程
王六米。4 小时前
RAG知识库建设 文档解析 切分与索引如何衔接
服务器·前端·网络·企业数字化转型·智钳智能盒子
Ivanqhz4 小时前
Ping-Pong 双缓冲
开发语言·人工智能·python·深度学习·mlir
名字还没想好☜4 小时前
React 文件上传实战:预览 URL 回收、多文件逐个进度与拖拽放置区踩坑
前端·react·next.js
m0_734571764 小时前
深入理解C++ RAII
开发语言·c++
console.log('npc')4 小时前
06 — Model 层:数据模型与操作
前端·后端·node.js·express