踩坑:Vue 模版中用到的响应式数据,不要在异步操作中给出声明
问题描述
2023/06/04
今天在学习时,看黑马的视频,小兔鲜的前端项目。
目标 数据是对象数组类型,但是视频中将目标数据使用ref()来生成
心里很不得劲,因为在我的习惯中,只有基本数据类型才用ref(),对象和数组类型要使用reactive()
这个目标数据是通过异步请求获取到的,在异步请求的会调函数中,完成对响应式数据的赋值。
视频中完整的代码是这样的:
<script setup> // 导入封装的异步api import { getCategoryAPI } from '@/api/home' import { ref } from 'vue' // 定义响应式数据 const category = ref([]) // 封装请求函数 async function getCategory(){ const res = await getCategory() // 赋值 // res.result是一个普通数组 category.value = res.result } </script> <template> <!-- 渲染数据 --> <ul> <li v-for="item in category" :key="item.id"> ... </li> </ul> </template>
这个代码执行起来是没有问题的,成功拿到数据,页面成功渲染。
我想要通过reactive()来定义,然后我的代码是这样的
我是这样想的:
- 如果代码是这样的
import { reactive } from 'vue' // 定义响应式数据 const category = reactive([]) async function getCategory(){ const res = await getCategoryAPI() // category失去响应式 category = res.result }
- 如果代码是这样
import { reactive } from 'vue' // 定义响应式数据 const category = reactive([]) async function getCategory(){ const res = await getCategoryAPI() // 等于重新创建了一个响应式对象 // 虽然可以实现响应式数据 // 但是之前的那个空数组就浪费了 // 所以我不想这样 category = reactive(res.result) }
最终经过我的“深思熟虑”,代码是这样的
import { reactive } from 'vue' // 定义一个数据 const category async function getCategory(){ const res = await getCategoryAPI() // 此时赋值并规定category是一个响应式的数据 category = reactive(res.result) }
这样做的问题是:可以成功获取到数据,通过Devtools调试发现,category也是一个响应式数据,但是页面渲染不出来。
纳闷了~~~
解析
一开始,我以为是reactive()函数与异步请求的有冲突,哈哈~~
晚上吃饭的时候,突然想到了。
分析:
- 浏览器在执行 到此异步请求函数时,发现是异步的,就不管了,继续解析下面的代码
- 当解析到模版时,此时的category还只是一个普通变量,不是响应式数据,而且是空的
- 页面当做普通的变量来渲染,所以页面不会渲染出来
- 当异步请求完成时,此时category才是响应式的了,但是并不会触发页面的重新渲染,只有当这个category中的内容被修改时,我们页面才将数据渲染出来。
都是基础知识不牢固惹的祸。
● 在视频中的代码,异步请求前,就规定了category这个变量是响应式的了,
● 模版此时解析的是一个响应式数据
● 当异步请求结束后,category中有了数据,模版重新渲染。
😁改进
所以,要想使用reactive()来接收响应式数据数组,而且又不想浪费空间,可以这样
● 先将category定义为响应式数据
● 在异步请求中,将接收的数据追加到category中
const category = reactive([]) async function getCategory(){ const res = await getCategoryAPI() category.push(...res.result) }
总结
模版要用到的响应式数据,不要在异步操作中定义/声明成响应式,而是应该在异步请求前完成对响应式的定义、声明。
分类:
BUG\踩坑
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现