有 A 、B 两个 API ,其中 B 的结果需要依赖 A 的结果来组装数据(类似于 B 是用户表存了角色 ID ,界面显示的时候需要依赖 A 角色表里的角色名称),之前的做法是在onMounted里先调用 A 然后再调用 B ,其中 A 被调用后我就把结果存起来了,只用调用这一次。
现在我封装了一个分页组件,于是我不在onMounted里调用 B 了,直接watch页码和页大小有变化的时候调用 B ,但是这样会导致一个问题:就是页面一加载的时候 watch 就会生效,导致 B 比 A 先执行。但是我又不想把 A 也放在watch里,因为它的数据几乎是不会变的,类似于角色表,页面加装的时候调用一次即可,大佬们有什么思路吗?
type Role = { id: string; name: string }; function usePage < T > () { const role = ref < Role | null > (null) const loading = ref(false); const page = reactive({ current: 1, size: 10 }); const uri = computed(() = >` / api / b ? page = $ { page.current } & size = $ { page.size }`); const { data, error, execute } = useFetch(uri, { immediate: false }).json < T > () // 防抖避免快速点击翻页按钮发送无效请求 const onLoadPageData = debounce(async() = >{ try { loading.value = true; await initRole(); await execute(); } finally { loading.value = false; } }, 200) async function initRole() { if (role.value) return; const { data, error } = await useFetch("/api/a").json < Role > (); if (error.value) { /** @todo error handler */ } else { role.value = data.value; onLoadPageData(); } } initRole(); watch(page, onLoadPageData, { immediate: true }); return { page, data, error, loading, onLoadPageData } }下面是一个简单的示例代码,说明了这个思路:
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 的数据。