Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ion-vue-router #17821

Merged
merged 4 commits into from
Mar 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion vue/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ function baseConfig() {
'@ionic/core/dist/ionic/svg',
'ionicons/dist/collection/icon/icon.css',
],
plugins: [vue(), typescript({ useTsconfigDeclarationDir: true })],
plugins: [
vue(),
typescript({
useTsconfigDeclarationDir: true,
objectHashIgnoreUnknownHack: true,
clean: true
})
],
}
}

Expand Down
16 changes: 0 additions & 16 deletions vue/src/components/ion-vue-router-transitionless.vue

This file was deleted.

149 changes: 149 additions & 0 deletions vue/src/components/ion-vue-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import Vue, { CreateElement, RenderContext, VNodeData } from 'vue';

type TransitionDone = () => void;
interface Props {
name: string;
animated: boolean;
}

// Component entering the view
let enteringEl: HTMLElement;

export default {
name: 'IonVueRouter',
functional: true,

props: {
// Router view name
name: { default: 'default', type: String },
// Disable transitions
animated: { default: true, type: Boolean },
},

render(h: CreateElement, { parent, props, data, children }: RenderContext) {
if (!parent.$router) {
throw new Error('IonTabs requires an instance of either VueRouter or IonicVueRouter');
}

const ionRouterOutletData: VNodeData = {
...data,
ref: 'ionRouterOutlet',
on: { click: (event: Event) => catchIonicGoBack(parent, event) },
};
const routerViewData: VNodeData = { props: { name: props.name } };
const transitionData: VNodeData = {
props: { css: false, mode: 'in-out' },
on: {
leave: (el: HTMLElement, done: TransitionDone) => {
leave(parent, props as Props, el, done);
},
beforeEnter,
enter,
afterEnter,
beforeLeave,
afterLeave,
enterCancelled,
leaveCancelled,
}
};

return h('ion-router-outlet', ionRouterOutletData, [
h('transition', transitionData, [
h('router-view', routerViewData, children)
])
]);
}
};

function catchIonicGoBack(parent: Vue, event: Event): void {
if (!event.target) return;

// We only care for the event coming from Ionic's back button
const backButton = (event.target as HTMLElement).closest('ion-back-button') as HTMLIonBackButtonElement;
if (!backButton) return;

const $router = parent.$router;
let defaultHref: string;

// Explicitly override router direction to always trigger a back transition
$router.directionOverride = -1;

// If we can go back - do so
if ($router.canGoBack()) {
event.preventDefault();
$router.back();
return;
}

// If there's a default fallback - use it
defaultHref = backButton.defaultHref as string;
if (undefined !== defaultHref) {
event.preventDefault();
$router.push(defaultHref);
}
}

// Transition when we leave the route
function leave(parent: Vue, props: Props, el: HTMLElement, done: TransitionDone) {
const promise = transition(parent, props, el);

// Skip any transition if we don't get back a Promise
if (!promise) {
done();
return;
}

// Perform navigation once the transition was finished
parent.$router.transition = new Promise(resolve => {
promise.then(() => {
resolve();
done();
}).catch(console.error);
});
}

// Trigger the ionic/core transitions
function transition(parent: Vue, props: Props, leavingEl: HTMLElement) {
const ionRouterOutlet = parent.$refs.ionRouterOutlet as HTMLIonRouterOutletElement;

// 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: HTMLIonRouterOutletElement) => {
return el.commit(enteringEl, leavingEl, {
deepWait: true,
duration: !props.animated ? 0 : undefined,
direction: parent.$router.direction === 1 ? 'forward' : 'back',
showGoBack: parent.$router.canGoBack(),
});
}).catch(console.error);
}

// Set the component to be rendered before we render the new route
function beforeEnter(el: HTMLElement) {
enteringEl = el;
}

// Enter the new route
function enter(_el: HTMLElement, done: TransitionDone) {
done();
}

// Vue transition stub functions
function afterEnter(_el: HTMLElement) { /* */ }
function afterLeave(_el: HTMLElement) { /* */ }
function beforeLeave(_el: HTMLElement) { /* */ }
function enterCancelled(_el: HTMLElement) { /* */ }
function leaveCancelled(_el: HTMLElement) { /* */ }
134 changes: 0 additions & 134 deletions vue/src/components/ion-vue-router.vue

This file was deleted.

5 changes: 3 additions & 2 deletions vue/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ declare module 'vue-router/types/router' {
interface VueRouter {
direction: number;
directionOverride: number | null;
transition: Promise<void>;
canGoBack(): boolean;
}
}
Expand Down Expand Up @@ -60,8 +61,8 @@ export interface ApiCache {
}

export interface RouterArgs extends RouterOptions {
direction: number;
viewCount: number;
direction?: number;
viewCount?: number;
}

export interface ProxyControllerInterface {
Expand Down
2 changes: 1 addition & 1 deletion vue/src/ionic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { IonicConfig } from '@ionic/core';
import { appInitialize } from './app-initialize';
import { VueDelegate } from './controllers/vue-delegate';
import IonTabs from './components/navigation/IonTabs';
import IonTabs from './components/navigation/ion-tabs';

export interface Controllers {
actionSheetController: ActionSheetController;
Expand Down
35 changes: 0 additions & 35 deletions vue/src/mixins/catch-ionic-go-back.ts

This file was deleted.

Loading