使用composition API和onBeforeRouteUpdate时,如何正确地抽象数据加载



我有一个Vue 3单页组件,其脚本部分大致如下:

export default defineComponent({
props: {
id: String,
},
setup(props) {
const error = ref<boolean>(false)
const thisCategory = ref<CategoryDetails>()
const subcategories= ref<Category[]>()
const fetchData = (categoryId: string) => {
fetchCategoryDetails(categoryId)
.then((v) => {
thisCategory.value = v
subcategories.value = v.child_categories
})
.catch(() => error.value = true)
}
fetchData(props.id || "")
onBeforeRouteUpdate((to) => fetchData(to.params.id as string))
return {
error,
thisCategory,
subcategories,
}
}
})

fetchData是我用来获取视图所需数据的函数。正如您所看到的,我使用它两次:一次是在setup((本身中,在组件首次实例化时加载数据,然后是onBeforeRouteUpdate,这样该组件内部链接到同一组件(但要获取不同的数据(的链接将实际加载新数据。

我预计其他组件也需要这样做,所以我想把这种行为抽象出来,但我似乎无法让它发挥作用。

另一个问题是,当我直接调用函数时,我从props获得ID,但在路由保护内部,我必须使用to.params,否则新ID将无法正确加载。

我如何将这个过程抽象为一个函数,我可以在每个组件中简单地调用它(也许只传递一个像fetchData这样的闭包(,它将处理初始加载数据和导航更改时的加载?

更新

如果您只想抽象error并添加onBeforeRouteUpdate侦听器,您仍然需要通过父级处理变量的填充,因此您需要通过传递的方法处理局部变量(如thisCategorysubcategories(的更新。

import { ref, computed } from "vue";
import { onBeforeRouteUpdate } from "vue-router";
export const STATE = {
INIT: "INIT",
LOADING: "LOADING",
SUCCESS: "SUCCESS",
ERROR: "ERROR",
};
export const withFetchResource = (fetchMethod, id) => {
const loadingState = ref(STATE.INIT);
const error = computed(() => loadingState.value === STATE.ERROR);
const fetchData = (resourceId) => {
loadingState.value = STATE.LOADING;
fetchMethod(resourceId)
.then((response) => {
loadingState.value = LOADING.SUCCESS;
return response;
})
.catch((error) => {
loadingState.value = LOADING.ERROR;
});
};
fetchData(id.value);
onBeforeRouteUpdate((to) => fetchData(to.params.id as string));
return { error, loadingState, fetchData };
};
import { ref, defineComponent } from "vue";
import { STATE, fetchCategoryDetails } from "./myApi.ts";
import { withFetchResource } from "./withFetchResource.ts";
export default defineComponent({
props: {
id: String,
},
setup(props) {
const thisCategory = ref<CategoryDetails>();
const subcategories = ref<Category[]>();
const categoryFetchHandler = (id) => {
return fetchCategoryDetails(id).then((v) => {
thisCategory.value = v;
subcategories.value = v.child_categories;
});
};
const { error: categoryError } = withFetchResource(
categoryFetchHandler,
props.id || ""
);
return {};
},
});

我认为您可以将整个文件/方法移动到另一个文件/方法中。

// withFetchCategoryDetail.ts
import {ref} from "vue";
import {onBeforeRouteUpdate} from "vue-router";
import {fetchCategoryDetails} from "./myApi.ts";
export const withFetchCategoryDetail = (props) => {
const error = ref<boolean>(false)
const thisCategory = ref<CategoryDetails>()
const subcategories= ref<Category[]>()
const fetchData = (categoryId: string) => {
fetchCategoryDetails(categoryId)
.then((v) => {
thisCategory.value = v
subcategories.value = v.child_categories
})
.catch(() => error.value = true)
}
fetchData(props.id || "")
onBeforeRouteUpdate((to) => fetchData(to.params.id as string))
return {
error,
thisCategory,
subcategories,
}
}
import { ref, onBeforeRouteUpdate, defineComponent } from "vue";
import { withFetchCategoryDetail } from "./withFetchCategoryDetail.ts";
export default defineComponent({
props: {
id: String,
},
setup(props) {
return {
...withFetchCategoryDetail(props)
};
},
});

我还没有测试onBeforeRouteUpdate是否能在hook方法中工作,但不明白为什么它不能

最新更新