Skip to content
Permalink
Browse files

feat(vue): support ion-vue-router (#17821)

  • Loading branch information...
michaeltintiuc authored and mhartington committed Mar 22, 2019
1 parent ee71675 commit 71e5994c941db768369c81b6660bb9926ce7a799
@@ -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
})
],
}
}

This file was deleted.

@@ -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) { /* */ }

This file was deleted.

@@ -6,6 +6,7 @@ declare module 'vue-router/types/router' {
interface VueRouter {
direction: number;
directionOverride: number | null;
transition: Promise<void>;
canGoBack(): boolean;
}
}
@@ -60,8 +61,8 @@ export interface ApiCache {
}

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

export interface ProxyControllerInterface {
@@ -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;

This file was deleted.

0 comments on commit 71e5994

Please sign in to comment.
You can’t perform that action at this time.