defineColadaLoader
All checks were successful
/ depcheck (push) Successful in 1m12s
/ build-and-deploy-to-vercel (push) Successful in 2m2s
/ playwright (push) Successful in 1m25s

This commit is contained in:
严浩
2024-12-20 14:53:31 +08:00
parent a8ce2f39e2
commit 89eae5bcbb
5 changed files with 160 additions and 0 deletions

View File

@ -31,6 +31,7 @@
"dependencies": {
"@alova/adapter-axios": "^2.0.12",
"@intlify/unplugin-vue-i18n": "^6.0.1",
"@pinia/colada": "^0.13.0",
"@primevue/themes": "^4.2.5",
"@unhead/vue": "^1.11.14",
"@vant/use": "^1.6.0",

8
pnpm-lock.yaml generated
View File

@ -17,6 +17,9 @@ importers:
'@intlify/unplugin-vue-i18n':
specifier: ^6.0.1
version: 6.0.1(@vue/compiler-dom@3.5.13)(eslint@9.17.0(jiti@2.4.2))(rollup@4.28.1)(typescript@5.7.2)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
'@pinia/colada':
specifier: ^0.13.0
version: 0.13.0
'@primevue/themes':
specifier: ^4.2.5
version: 4.2.5
@ -1020,6 +1023,9 @@ packages:
cpu: [x64]
os: [win32]
'@pinia/colada@0.13.0':
resolution: {integrity: sha512-Ah6uv1spRCu3I0QmimOMwrkKMcQK1+Ov2Qroz4PFD2/i9gwRUddj7Pz9kNcg5xXp2WWEPmnvkhTr2GgdqTUaUQ==}
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@ -5849,6 +5855,8 @@ snapshots:
'@oxc-resolver/binding-win32-x64-msvc@2.1.1':
optional: true
'@pinia/colada@0.13.0': {}
'@pkgjs/parseargs@0.11.0':
optional: true

View File

@ -33,6 +33,8 @@ const {
reload, // a function to refetch the data without navigating
} = usePageData();
const route = useRoute('DataLoadersId');
watch(
pageData,
(pageDataVal) => {
@ -50,6 +52,13 @@ watch(
<template>
<h1>Data Loaders</h1>
<ul>
<li>
<RouterLink class="green" :to="{ name: 'DataLoadersIdSub1UserId', params: { id: route.params.id, userId: '1' } }"
>sub-1</RouterLink
>
</li>
</ul>
<div flex="~ row">
<button class="green" @click="$router.back()">Back</button>
<button class="green" @click="reload()">Reload</button>

View File

@ -0,0 +1,141 @@
<script lang="ts">
import { defineColadaLoader } from 'unplugin-vue-router/data-loaders/pinia-colada';
async function getUserById(id: string, { signal }: { signal?: AbortSignal }) {
console.warn('[getUserById] 被调用, id :>> ', id);
setTimeout(() => {
console.log('5s 已过', 'id :>> ', id);
}, 5000);
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, { signal });
await new Promise((resolve) => setTimeout(resolve, 300));
return await res.json();
}
export const useUserData = defineColadaLoader('DataLoadersIdSub1UserId', {
async query(to, { signal }) {
console.debug('[defineColadaLoader] query');
return getUserById(to.params.userId, { signal });
},
key: (to) => ['users', to.params.userId],
// Keep the data "fresh" 10 seconds to avoid fetching the same data too often
// 保持数据“新鲜”10秒以避免过于频繁地获取相同的数据
staleTime: 5000,
});
</script>
<script setup lang="ts">
const { data: user, status, error, isLoading, reload, refresh } = useUserData();
const route = useRoute('DataLoadersIdSub1UserId');
</script>
<template>
<div flex="~ row">
<button class="green" @click="$router.back()">Back</button>
</div>
<h1>Pinia Colada Loader Example</h1>
<pre>route.params: {{ route.params }}</pre>
<fieldset>
<legend>Controls</legend>
<button @click="refresh()">Refresh</button>
<button @click="reload()">Refetch</button>
</fieldset>
<div class="flex items-center">
<RouterLink :to="{ params: { userId: (Number(route.params.userId) || 0) - 1 } }">
Previous
{{ (Number(route.params.userId) || 0) - 1 }}
</RouterLink>
|
<RouterLink :to="{ params: { userId: (Number(route.params.userId) || 0) + 1 } }">
Next {{ (Number(route.params.userId) || 0) + 1 }}
</RouterLink>
</div>
<h2>State</h2>
<p>
<code>status: {{ status }}</code>
<br />
<code>isLoading: {{ isLoading }}</code>
</p>
<pre v-if="error">Error: {{ error }}</pre>
<pre v-else>{{ user == null ? String(user) : user }}</pre>
</template>
<style scoped>
.green {
background-color: #42b883;
color: #ffffff;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin-bottom: 16px;
}
fieldset {
border: 1px solid #4a4a4a;
padding: 16px;
margin: 16px 0;
border-radius: 8px;
background-color: #2a2a2a;
}
legend {
padding: 0 8px;
color: #b3b3b3;
}
button {
margin-right: 8px;
padding: 6px 12px;
border: 1px solid #4a4a4a;
border-radius: 4px;
cursor: pointer;
background-color: #333333;
color: #ffffff;
}
button:hover {
background-color: #444444;
}
pre {
background-color: #1e1e1e;
padding: 16px;
border-radius: 6px;
overflow-x: auto;
color: #e0e0e0;
}
code {
background-color: #2a2a2a;
padding: 2px 6px;
border-radius: 4px;
color: #e0e0e0;
}
a {
color: #42b883;
text-decoration: none;
padding: 4px 8px;
}
a:hover {
text-decoration: underline;
color: #5ccfaa;
}
h1 {
color: #e0e0e0;
margin-bottom: 20px;
}
h2 {
color: #42b883;
margin-top: 24px;
}
</style>

1
typed-router.d.ts vendored
View File

@ -24,6 +24,7 @@ declare module 'vue-router/auto-routes' {
'AA': RouteRecordInfo<'AA', '/a/a', Record<never, never>, Record<never, never>>,
'Api': RouteRecordInfo<'Api', '/api', Record<never, never>, Record<never, never>>,
'DataLoadersId': RouteRecordInfo<'DataLoadersId', '/data-loaders/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'DataLoadersIdSub1UserId': RouteRecordInfo<'DataLoadersIdSub1UserId', '/data-loaders/:id/sub-1/:userId', { id: ParamValue<true>, userId: ParamValue<true> }, { id: ParamValue<false>, userId: ParamValue<false> }>,
'IndexPage': RouteRecordInfo<'IndexPage', '/index-page', Record<never, never>, Record<never, never>>,
'InfiniteLoading': RouteRecordInfo<'InfiniteLoading', '/infinite-loading', Record<never, never>, Record<never, never>>,
'MdPage': RouteRecordInfo<'MdPage', '/md-page', Record<never, never>, Record<never, never>>,