踩坑: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()来定义,然后我的代码是这样的
我是这样想的:

  1. 如果代码是这样的
import { reactive } from 'vue'
// 定义响应式数据
const category = reactive([])
async function getCategory(){
const res = await getCategoryAPI()
// category失去响应式
category = res.result
}
  1. 如果代码是这样
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()函数与异步请求的有冲突,哈哈~~
晚上吃饭的时候,突然想到了。
分析:

  1. 浏览器在执行 到此异步请求函数时,发现是异步的,就不管了,继续解析下面的代码
  2. 当解析到模版时,此时的category还只是一个普通变量,不是响应式数据,而且是空的
  3. 页面当做普通的变量来渲染,所以页面不会渲染出来
  4. 当异步请求完成时,此时category才是响应式的了,但是并不会触发页面的重新渲染,只有当这个category中的内容被修改时,我们页面才将数据渲染出来。
    都是基础知识不牢固惹的祸。
    ● 在视频中的代码,异步请求前,就规定了category这个变量是响应式的了,
    ● 模版此时解析的是一个响应式数据
    ● 当异步请求结束后,category中有了数据,模版重新渲染。

😁改进
所以,要想使用reactive()来接收响应式数据数组,而且又不想浪费空间,可以这样
● 先将category定义为响应式数据
● 在异步请求中,将接收的数据追加到category中

const category = reactive([])
async function getCategory(){
const res = await getCategoryAPI()
category.push(...res.result)
}

总结
模版要用到的响应式数据,不要在异步操作中定义/声明成响应式,而是应该在异步请求前完成对响应式的定义、声明。

posted @   秋天Code  阅读(17)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示