Skip to content

Commit f82fb8f

Browse files
committed
feat: add route transition animation
1 parent e66562d commit f82fb8f

File tree

11 files changed

+148
-43
lines changed

11 files changed

+148
-43
lines changed

app.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import type { ConfigProviderTheme } from 'vant'
3+
import useRouteTransitionName from '~/composables/transitions'
34
import useKeepalive from '~/composables/keepalive'
45
import { appName } from '~/constants'
56
@@ -8,19 +9,26 @@ useHead({
89
})
910
1011
const color = useColorMode()
11-
const mode = computed(() => color.value as ConfigProviderTheme)
12+
13+
const mode = computed(() => {
14+
return color.value as ConfigProviderTheme
15+
})
1216
1317
const keepAliveRouteNames = computed(() => {
1418
return useKeepalive().routeCaches as string[]
1519
})
20+
21+
const transitionName = computed(() => {
22+
return useRouteTransitionName().routeTransitionName
23+
})
1624
</script>
1725

1826
<template>
1927
<VanConfigProvider :theme="mode">
2028
<ColorScheme tag="div">
21-
<NuxtLoadingIndicator />
29+
<NuxtLoadingIndicator color="repeating-linear-gradient(to right,var(--c-primary) 0%,var(--c-primary-active) 100%)" />
2230
<NuxtLayout>
23-
<NuxtPage :keepalive="{ include: keepAliveRouteNames }" />
31+
<NuxtPage :keepalive="{ include: keepAliveRouteNames }" :transition="{ name: transitionName }" />
2432
</NuxtLayout>
2533
</ColorScheme>
2634
</VanConfigProvider>

components/Container.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script setup lang="ts">
2+
defineProps({
3+
paddingX: {
4+
type: Number,
5+
default: 16,
6+
},
7+
})
8+
</script>
9+
10+
<template>
11+
<div
12+
class="absolute left-0 h-full w-full overflow-y-auto"
13+
:style="`padding-left: ${paddingX}px; padding-right: ${paddingX}px`"
14+
>
15+
<slot />
16+
</div>
17+
</template>

composables/transitions.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineStore } from 'pinia'
2+
3+
const useRouteTransitionName = defineStore('route-transition-name', () => {
4+
const routeTransitionName = ref('')
5+
6+
const setName = (name: string) => {
7+
routeTransitionName.value = name
8+
}
9+
10+
return {
11+
routeTransitionName,
12+
setName,
13+
}
14+
})
15+
16+
export default useRouteTransitionName

index.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
declare module '#app' {
2+
interface PageMeta {
3+
level?: number
4+
}
5+
}
6+
7+
export {}

middleware/route.global.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import useKeepalive from '~/composables/keepalive'
2+
import routeTransitionNameStore from '~/composables/transitions'
3+
import type { RouteLocationNormalized } from '#vue-router'
24

3-
export default defineNuxtRouteMiddleware((to) => {
5+
export default defineNuxtRouteMiddleware((to: RouteLocationNormalized, from) => {
6+
// KeepAlive
47
if (to.meta && to.meta.keepalive)
58
useKeepalive().addRoute(to)
9+
10+
// Set route transition name
11+
if (!to.meta.level || !from.meta.level)
12+
return
13+
14+
if (to.meta.level > from.meta.level)
15+
routeTransitionNameStore().setName('slide-fadein-left')
16+
17+
else if (to.meta.level < from.meta.level)
18+
routeTransitionNameStore().setName('slide-fadein-right')
19+
20+
else
21+
routeTransitionNameStore().setName('')
622
})

pages/[...all].vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ definePageMeta({
55
</script>
66

77
<template>
8-
<div> {{ $t('error_page.txt') }} </div>
8+
<Container>
9+
<div> {{ $t('error_page.txt') }} </div>
10+
</Container>
911
</template>

pages/index.vue

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import type { ComputedRef } from 'vue'
44
import type { LocaleObject } from '@nuxtjs/i18n'
55
import { Locale } from 'vant'
66
7+
definePageMeta({
8+
level: 1,
9+
})
10+
711
const color = useColorMode()
812
913
useHead({
@@ -52,37 +56,39 @@ function onLanguageConfirm(event: { selectedOptions: PickerColumn }) {
5256
</script>
5357

5458
<template>
55-
<VanCellGroup inset>
56-
<VanCell :title="$t('menu.darkMode')" center>
57-
<template #right-icon>
58-
<VanSwitch
59-
v-model="checked"
60-
size="20px"
61-
aria-label="on/off Dark Mode"
62-
@click="toggleDark"
63-
/>
64-
</template>
65-
</VanCell>
66-
67-
<VanCell
68-
:title="$t('menu.language')"
69-
:value="locales.find(i => i.code === i18n.locale.value)?.name"
70-
is-link
71-
@click="showLanguagePicker = true"
72-
/>
73-
74-
<van-popup v-model:show="showLanguagePicker" position="bottom">
75-
<van-picker
76-
v-model="languageValues"
77-
:columns="locales"
78-
:columns-field-names="{ text: 'name', value: 'code' }"
79-
@confirm="onLanguageConfirm"
80-
@cancel="showLanguagePicker = false"
59+
<Container :padding-x="0">
60+
<VanCellGroup inset>
61+
<VanCell :title="$t('menu.darkMode')" center>
62+
<template #right-icon>
63+
<VanSwitch
64+
v-model="checked"
65+
size="20px"
66+
aria-label="on/off Dark Mode"
67+
@click="toggleDark"
68+
/>
69+
</template>
70+
</VanCell>
71+
72+
<VanCell
73+
:title="$t('menu.language')"
74+
:value="locales.find(i => i.code === i18n.locale.value)?.name"
75+
is-link
76+
@click="showLanguagePicker = true"
8177
/>
82-
</van-popup>
8378

84-
<template v-for="item in menus" :key="item.route">
85-
<VanCell :title="item.title" :to="item.route" is-link />
86-
</template>
87-
</VanCellGroup>
79+
<van-popup v-model:show="showLanguagePicker" position="bottom">
80+
<van-picker
81+
v-model="languageValues"
82+
:columns="locales"
83+
:columns-field-names="{ text: 'name', value: 'code' }"
84+
@confirm="onLanguageConfirm"
85+
@cancel="showLanguagePicker = false"
86+
/>
87+
</van-popup>
88+
89+
<template v-for="item in menus" :key="item.route">
90+
<VanCell :title="item.title" :to="item.route" is-link />
91+
</template>
92+
</VanCellGroup>
93+
</Container>
8894
</template>

pages/keepalive/index.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ definePageMeta({
88
keepalive: true,
99
title: '🧡 KeepAlive',
1010
i18n: 'menu.keepAlive',
11+
level: 2,
1112
})
1213
1314
const value = ref(1)
1415
</script>
1516

1617
<template>
17-
<div>
18+
<Container>
1819
<p>{{ $t('keepalive_page.label') }}</p>
1920
<van-stepper v-model="value" />
20-
</div>
21+
</Container>
2122
</template>

pages/profile/index.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
<script setup lang="ts">
2+
definePageMeta({
3+
level: 1,
4+
})
5+
</script>
6+
17
<template>
2-
<div mx-auto mb-60 pt-15 text-center text-16 text-dark dark:text-white>
3-
{{ $t('profile_page.txt') }}
4-
</div>
8+
<Container>
9+
<div mx-auto mb-60 pt-15 text-center text-16 text-dark dark:text-white>
10+
{{ $t('profile_page.txt') }}
11+
</div>
12+
</Container>
513
</template>

pages/unocss/index.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
definePageMeta({
33
title: '🎨 Unocss 示例',
44
i18n: 'menu.unocssExample',
5+
level: 2,
56
})
67
</script>
78

89
<template>
9-
<div>
10+
<Container>
1011
<h1 class="text-6xl color-pink font-semibold">
1112
{{ $t('unocss_page.hello', ['Unocss!']) }}
1213
</h1>
@@ -18,5 +19,5 @@ definePageMeta({
1819
<button class="mt-10 btn">
1920
{{ $t('unocss_page.btn_txt') }}
2021
</button>
21-
</div>
22+
</Container>
2223
</template>

0 commit comments

Comments
 (0)