/
ion-vue-router.vue
134 lines (115 loc) · 3.72 KB
/
ion-vue-router.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<template>
<ion-router-outlet
ref="ionRouterOutlet"
@click="catchIonicGoBack">
<router-view
v-if="customTransition"
:name="name"/>
<transition
v-else
:css="bindCSS"
mode="in-out"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
>
<router-view :name="name"/>
</transition>
</ion-router-outlet>
</template>
<script lang="ts">
import { Prop } from 'vue-property-decorator';
import Component, { mixins } from 'vue-class-component';
import CatchIonicGoBack from '../mixins/catch-ionic-go-back';
import { IonRouterOutlet } from '../interfaces';
@Component
export default class IonVueRouter extends mixins(CatchIonicGoBack) {
@Prop({ default: 'default'}) name!: string;
@Prop({ default: false }) bindCSS!: boolean;
@Prop({ default: true }) animated!: boolean;
// Currently visible component
leavingEl: HTMLElement;
// Component to be rendered
enteringEl: HTMLElement;
// Flag to see if we're still in a transition
inTransition = false;
customTransition = false;
created() {
// Cancel navigation if there's a running transition
this.$router.beforeEach((to, _from, next) => {
this.customTransition = to.meta.customTransition || false
return this.$nextTick(() => {
return next(!this.inTransition as false);
})
})
}
transition(enteringEl: HTMLElement, leavingEl: HTMLElement) {
// Get the reference to the Ionic component handling the transitions
const ionRouterOutlet = this.$refs.ionRouterOutlet as IonRouterOutlet;
// The Ionic framework didn't load - skip animations
if (typeof ionRouterOutlet.componentOnReady === 'undefined') {
return;
}
// Skip animations if there's no component to navigate to
// or the current and the "to-be-rendered" components are the same
if (!enteringEl || enteringEl === leavingEl) {
return;
}
// Add the proper Ionic classes, important for smooth transitions
enteringEl.classList.add('ion-page', 'ion-page-invisible')
// Commit to the transition as soon as the Ionic Router Outlet is ready
return ionRouterOutlet.componentOnReady().then(el => {
return el.commit(enteringEl, leavingEl, {
deepWait: true,
duration: this.getDuration(),
direction: this.getDirection(),
showGoBack: this.$router.canGoBack(),
});
});
}
// Instant transition if we don't want to animate
getDuration() {
return !this.animated ? 0 : undefined;
}
// Get the navigation direction from the router
getDirection() {
return this.$router.direction === 1 ? 'forward' : 'back';
}
// Set the component to be rendered before we render the new route
beforeEnter(el: HTMLElement) {
this.enteringEl = el;
}
// Remember the current component before we leave the route
beforeLeave(el: HTMLElement) {
this.leavingEl = el;
}
// Transition when we leave the route
leave(el: HTMLElement, done: (opts?: boolean) => void): void {
const promise = this.transition(this.enteringEl, el);
this.inTransition = true;
// Skip any transition if we don't get back a Promise
if (!promise) {
this.inTransition = false;
return done();
}
// Perform navigation once the transition was finished
promise.then(() => {
this.inTransition = false;
return done(true);
});
}
// Enter the new route
enter(_el: HTMLElement, done: () => void): void {
done();
}
afterEnter(/* el */) {}
enterCancelled(/* el */) {}
afterLeave(/* el */) {}
leaveCancelled(/* el */) {}
}
</script>