Skip to content

Commit 2b7300b

Browse files
committed
docs: transitions
1 parent 82d6bef commit 2b7300b

File tree

5 files changed

+99
-44
lines changed

5 files changed

+99
-44
lines changed

docs/guide/advanced/transitions.md

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,59 @@
11
# Transitions
22

3-
Since the `<router-view>` is essentially a dynamic component, we can apply transition effects to it the same way using the `<transition>` component:
3+
In order to use transitions on your route components and animate navigations, you need to use the [v-slot API](../../api#v-slot):
44

55
```html
6-
<router-view v-slot="{ Component }">
7-
<transition>
8-
<component :is="Component" />
9-
</transition>
10-
</router-view>
6+
<router-view v-slot="{ Component }">
7+
<transition name="fade">
8+
<component :is="Component" />
9+
</transition>
10+
</router-view>
1111
```
1212

1313
[All transition APIs](https://vuejs.org/guide/transitions.html) work the same here.
1414

1515
## Per-Route Transition
1616

17-
The above usage will apply the same transition for all routes. If you want each route's component to have different transitions, you can instead use `<transition>` with different names inside each route component:
17+
The above usage will apply the same transition for all routes. If you want each route's component to have different transitions, you can instead combine [meta fields](./meta.md) and a dynamic `name` on `<transition>`:
1818

1919
```js
20-
const Foo = {
21-
template: `
22-
<transition name="slide">
23-
<div class="foo">...</div>
24-
</transition>
25-
`
26-
}
27-
28-
const Bar = {
29-
template: `
30-
<transition name="fade">
31-
<div class="bar">...</div>
32-
</transition>
33-
`
34-
}
20+
const routes = [
21+
{ path: '/custom-transition', meta: { transition: 'slide-left' } },
22+
{ path: '/other-transition', meta: { transition: 'slide-right' } },
23+
]
24+
```
25+
26+
```html
27+
<router-view v-slot="{ Component, route }">
28+
<!-- Use any custom transition and fallback to `fade` -->
29+
<transition :name="route.meta.transition || 'fade'">
30+
<component :is="Component" />
31+
</transition>
32+
</router-view>
3533
```
3634

3735
## Route-Based Dynamic Transition
3836

39-
It is also possible to determine the transition to use dynamically based on the relationship between the target route and current route:
37+
It is also possible to determine the transition to use dynamically based on the relationship between the target route and current route. Using a very similar snippet to the one just before:
4038

4139
```html
4240
<!-- use a dynamic transition name -->
43-
<transition :name="transitionName">
44-
<router-view></router-view>
45-
</transition>
41+
<router-view v-slot="{ Component, route }">
42+
<transition :name="route.meta.transition">
43+
<component :is="Component" />
44+
</transition>
45+
</router-view>
4646
```
4747

48+
We can add an [after navigation hook](./navigation-guards.md#global-after-hooks) to dynamically add information to the `meta` field based on the depth of the route
49+
4850
```js
49-
// then, in the parent component,
50-
// watch the `$route` to determine the transition to use
51-
watch: {
52-
'$route' (to, from) {
53-
const toDepth = to.path.split('/').length
54-
const fromDepth = from.path.split('/').length
55-
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
56-
}
57-
}
51+
router.afterEach((to, from) => {
52+
const toDepth = to.path.split('/').length
53+
const fromDepth = from.path.split('/').length
54+
to.meta.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
55+
})
5856
```
5957

60-
See full example [here](https://github.com/vuejs/vue-router/blob/dev/examples/transitions/app.js).
58+
<!-- TODO: interactive example -->
59+
<!-- See full example [here](https://github.com/vuejs/vue-router/blob/dev/examples/transitions/app.js). -->

playground/App.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,22 +159,23 @@
159159
<button @click="toggleViewName">Toggle view</button>
160160
<Suspense>
161161
<template #default>
162-
<router-view :name="viewName" v-slot="{ Component }">
162+
<router-view :name="viewName" v-slot="{ Component, route }">
163163
<transition
164-
name="fade"
164+
:name="route.meta.transition || 'fade'"
165165
mode="out-in"
166166
@before-enter="flushWaiter"
167167
@before-leave="setupWaiter"
168168
>
169169
<keep-alive>
170-
<component :is="Component" />
170+
<component
171+
:is="Component"
172+
:key="route.name === 'repeat' ? route.path : undefined"
173+
/>
171174
</keep-alive>
172175
</transition>
173176
</router-view>
174177
</template>
175-
<template #fallback>
176-
Loading...
177-
</template>
178+
<template #fallback> Loading... </template>
178179
</Suspense>
179180
</div>
180181
</template>

playground/index.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
}
2121
.fade-enter-active,
2222
.fade-leave-active {
23-
transition: opacity 0.15s ease;
23+
transition: opacity 0.3s ease;
2424
}
2525
.fade-enter-from,
2626
.fade-leave-to {
@@ -30,6 +30,12 @@
3030
position: absolute;
3131
transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1);
3232
}
33+
.slide-left-enter-active,
34+
.slide-left-leave-active,
35+
.slide-right-enter-active,
36+
.slide-right-leave-active {
37+
transition: all 0.3s;
38+
}
3339
.slide-left-enter-from,
3440
.slide-right-leave-to {
3541
opacity: 0;

playground/router.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import GuardedWithLeave from './views/GuardedWithLeave.vue'
1414
import ComponentWithData from './views/ComponentWithData.vue'
1515
import { globalState } from './store'
1616
import { scrollWaiter } from './scrollWaiter'
17+
import RepeatedParams from './views/RepeatedParams.vue'
1718
let removeRoute: (() => void) | undefined
1819

1920
export const routerHistory = createWebHistory()
@@ -42,6 +43,7 @@ export const router = createRouter({
4243
{ path: '/long-:n', name: 'long', component: LongView },
4344
{
4445
path: '/lazy',
46+
meta: { transition: 'slide-left' },
4547
component: async () => {
4648
await delay(500)
4749
return component()
@@ -77,7 +79,7 @@ export const router = createRouter({
7779
],
7880
},
7981
{ path: '/with-data', component: ComponentWithData, name: 'WithData' },
80-
{ path: '/rep/:a*', component: component, name: 'repeat' },
82+
{ path: '/rep/:a*', component: RepeatedParams, name: 'repeat' },
8183
{ path: '/:data(.*)', component: NotFound, name: 'NotFound' },
8284
{
8385
path: '/nested',
@@ -189,6 +191,14 @@ router.beforeEach((to, from, next) => {
189191
next()
190192
})
191193

194+
router.afterEach((to, from) => {
195+
if (to.name === from.name && to.name === 'repeat') {
196+
const toDepth = to.path.split('/').length
197+
const fromDepth = from.path.split('/').length
198+
to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
199+
}
200+
})
201+
192202
router.afterEach((to, from) => {
193203
// console.log(
194204
// `After guard: from ${from.fullPath} to ${

playground/views/RepeatedParams.vue

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<template>
2+
<div>
3+
<div>Repeated Params</div>
4+
<router-link :to="lessNesting">Less nesting</router-link>
5+
<br />
6+
<router-link :to="moreNesting">More nesting</router-link>
7+
<pre>{{ moreNesting }}</pre>
8+
<pre>{{ lessNesting }}</pre>
9+
</div>
10+
</template>
11+
12+
<script>
13+
import { defineComponent, computed } from 'vue'
14+
import { useRoute } from '../../src'
15+
16+
export default defineComponent({
17+
name: 'RepeatedParams',
18+
19+
setup() {
20+
const route = useRoute()
21+
22+
const lessNesting = computed(() => {
23+
const a = [...(route.params.a || [])]
24+
a.pop()
25+
26+
return { params: { a } }
27+
})
28+
29+
const moreNesting = computed(() => {
30+
const a = [...(route.params.a || [])]
31+
a.push('more')
32+
33+
return { params: { a } }
34+
})
35+
36+
return { lessNesting, moreNesting }
37+
},
38+
})
39+
</script>

0 commit comments

Comments
 (0)