请教一个 Vue 请求后端 API 顺序问题

38 天前
 imherer

有 A 、B 两个 API ,其中 B 的结果需要依赖 A 的结果来组装数据(类似于 B 是用户表存了角色 ID ,界面显示的时候需要依赖 A 角色表里的角色名称)

之前的做法是在onMounted里先调用 A 然后再调用 B ,其中 A 被调用后我就把结果存起来了,只用调用这一次

现在我封装了一个分页组件,于是我不在onMounted里调用 B 了,直接watch页码和页大小有变化的时候调用 B ,但是这样会导致一个问题:就是页面一加载的时候 watch 就会生效,导致 B 比 A 先执行。但是我又不想把 A 也放在watch里,因为它的数据几乎是不会变的,类似于角色表,页面加装的时候调用一次即可

大佬们有什么思路吗?

3185 次点击
所在节点    程序员
42 条回复
Baymaxbowen
38 天前
把 A 放在父组件能调用?通过 props 传入结果到你的分页组件?
imherer
38 天前
@Baymaxbowen B 接口也是在父组件里调用的,分页组件它只处理页码或者页大小的变化,变化后会在父组件的 watch 里监控它 然后调用 B
InDom
38 天前
再包一两层?把 A B 分别包成两个函数,onMounted 里面调用 C ,C 取判断如果有 A 就调用 B ,如果没有 A 就先调用 A 。

这样你只需要找调用 B 的地方调用 C 即可。
imherer
38 天前
@InDom 有道理,这个方法可行
shenleiyin
38 天前
你可以考虑在你的分页组件中引入一个状态来表示 A 是否已经加载完成。这样,在组件加载时,你可以首先检查是否已经加载了 A 的数据。如果没有,那么首先加载 A ,然后再加载 B 。

下面是一个简单的示例代码,说明了这个思路:

import { ref, watch, onMounted } from 'vue';

export default {
setup() {
// 用于存储 A 的数据
const dataA = ref(null);
// 用于表示 A 是否已经加载完成
const isDataALoaded = ref(false);

// 模拟加载 A 的数据
function fetchDataA() {
// 这里假设 fetchDataA 是异步操作
setTimeout(() => {
// 模拟从 API 获取到的 A 的数据
const result = /* 调用 A 的 API */;
// 存储 A 的数据
dataA.value = result;
// 标记 A 已加载完成
isDataALoaded.value = true;
}, 1000); // 假设加载 A 的数据需要 1 秒钟
}

// 模拟加载 B 的数据
function fetchDataB(page, pageSize) {
// 这里假设 fetchDataB 是异步操作
setTimeout(() => {
// 只有在 A 的数据加载完成后才调用 B 的 API
if (isDataALoaded.value) {
// 这里可以使用 A 的数据来组装 B 的数据
const result = /* 调用 B 的 API ,依赖于 A 的数据 */;
console.log(result);
} else {
// 如果 A 的数据尚未加载完成,则等待 A 加载完成后再调用 B 的 API
console.log("Waiting for A to load...");
}
}, 500); // 假设加载 B 的数据需要 0.5 秒钟
}

// 监听页码和页大小的变化,当它们变化时调用 fetchDataB
watch([currentPage, pageSize], ([newPage, newPageSize], [oldPage, oldPageSize]) => {
fetchDataB(newPage, newPageSize);
});

// 在组件加载时,如果 A 的数据尚未加载,则先加载 A 的数据
onMounted(() => {
if (!isDataALoaded.value) {
fetchDataA();
}
});

return {
dataA,
isDataALoaded,
};
},
};

这样,无论在分页组件加载时还是在页码或页大小变化时,都会先检查 A 的数据是否已经加载完成,然后再决定是否加载 B 的数据。
corcre
38 天前
A 返回数据再动态绑定 B 的属性?好像是 this.$set 啥的
(但是好久不写 vue 了, 不知道是不是这么个思路
Stlin
38 天前
这个 A 接口是不是在系统中别的页面也需要用到的?就是这个角色是不是全局的,如果是这个就好办啦,直接放在入口( main.js 或者 router 钩子)请求后存 session 或 local storage ,这样你在别的页面直接取就行了。
HTML001
38 天前
提取一段公用代码,用来判断是否有 A 的数据,有就直接调用 B ,没有则先 A 后 B 。之前需要调用 B 方法的地方,都用这个公用代码就行
imherer
38 天前
@corcre 对的,A 返回数据再动态绑定 B 的属性。

我查查
imherer
38 天前
@Stlin 就当前页面用得到。A 的数据虽然大概率不会改,但是还是有改的情况,所以想法还是在这个页面加装的时候请求一次最新的数据最好
imherer
38 天前
@HTML001 嗯,有点类似于 3 楼的做法
rcocco
38 天前
上 tanstack query/vue ,你在任意地方调用一次,之后随便取就行了。
想长时间有效不重新请求就设置失效时间,想提前失效重新加载也有对应的 API
imherer
38 天前
@shenleiyin AI 回答的吧?这个有个问题,假如 A 请求超过 1s 的话会导致 B 不会执行啊
sqlNice
38 天前
分页组件 props 接收一个 beforeSearch 。在 watch 监听到变化执行你的 getData 方法(也就是 B )时 async 调用 beforeSearch 方法。
corcre
38 天前
imherer
38 天前
@rcocco 看了下,这玩儿挺强大呀,好像还可以做限流?
lizy0329
38 天前
1. 用 watch 监控
2. 用 vue-query
imherer
38 天前
@lizy0329 vue-query 是不是和 12L 说的 tanstack query/vue 一个功能?
zogwosh
38 天前
你可以在 onMounted 里调用 watch
duanxianze
38 天前
b 执行的时候判断是否有 userid 就行,没有直接 return,不用搞那么复杂,watch 里添加对 userid 变化的监测

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1040134

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX