fix(vue): correctly pass route props to components (#22476)

resolves #22472
This commit is contained in:
Liam DeBeasi
2020-11-11 12:12:12 -05:00
committed by GitHub
parent a4a64530ff
commit 0956f8bc55
4 changed files with 154 additions and 8 deletions

View File

@ -42,6 +42,7 @@ export interface ViewItem {
exact: boolean; exact: boolean;
registerCallback?: () => void; registerCallback?: () => void;
vueComponentRef: Ref; vueComponentRef: Ref;
params?: { [k: string]: any };
} }
export interface ViewStacks { export interface ViewStacks {

View File

@ -88,7 +88,8 @@ export const createViewStacks = () => {
vueComponentRef: shallowRef(), vueComponentRef: shallowRef(),
ionRoute: false, ionRoute: false,
mount: false, mount: false,
exact: routeInfo.pathname === matchedRoute.path exact: routeInfo.pathname === matchedRoute.path,
params: routeInfo.params
}; };
} }

View File

@ -355,15 +355,36 @@ export const IonRouterOutlet = defineComponent({
{ ref: 'ionRouterOutlet' }, { ref: 'ionRouterOutlet' },
// TODO types // TODO types
components && components.map((c: any) => { components && components.map((c: any) => {
let props = {
ref: c.vueComponentRef,
key: c.pathname,
isInOutlet: true,
registerIonPage: (ionPageEl: HTMLElement) => registerIonPage(c, ionPageEl)
}
/**
* IonRouterOutlet does not support named outlets.
*/
if (c.matchedRoute?.props?.default) {
const matchedRoute = c.matchedRoute;
const routePropsOption = matchedRoute.props.default;
const routeProps = routePropsOption
? routePropsOption === true
? c.params
: typeof routePropsOption === 'function'
? routePropsOption(matchedRoute)
: routePropsOption
: null
props = {
...props,
...routeProps
}
}
return h( return h(
c.vueComponent, c.vueComponent,
{ props
ref: c.vueComponentRef, );
key: c.pathname,
isInOutlet: true,
registerIonPage: (ionPageEl: HTMLElement) => registerIonPage(c, ionPageEl)
}
)
}) })
) )
} }

View File

@ -0,0 +1,123 @@
import { mount } from '@vue/test-utils';
import { createRouter, createWebHistory } from '@ionic/vue-router';
import { IonicVue, IonApp, IonRouterOutlet, IonPage, IonTabs, IonTabBar } from '@ionic/vue';
const App = {
components: { IonApp, IonRouterOutlet },
template: '<ion-app><ion-router-outlet /></ion-app>',
}
const BasePage = {
template: '<ion-page :data-pageid="name"></ion-page>',
components: { IonPage },
}
describe('Routing', () => {
it('should pass no props', async () => {
const Page1 = {
...BasePage,
props: {
title: { type: String, default: 'Default Title' }
}
};
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
{ path: '/', component: Page1 }
]
});
router.push('/');
await router.isReady();
const wrapper = mount(App, {
global: {
plugins: [router, IonicVue]
}
});
const cmp = wrapper.findComponent(Page1);
expect(cmp.props()).toEqual({ title: 'Default Title' });
});
it('should pass route props as an object', async () => {
const Page1 = {
...BasePage,
props: {
title: { type: String, default: 'Default Title' }
}
};
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
{ path: '/', component: Page1, props: { title: 'Page 1 Title' } }
]
});
router.push('/');
await router.isReady();
const wrapper = mount(App, {
global: {
plugins: [router, IonicVue]
}
});
const cmp = wrapper.findComponent(Page1);
expect(cmp.props()).toEqual({ title: 'Page 1 Title' });
});
it('should pass route props as a function', async () => {
const Page1 = {
...BasePage,
props: {
title: { type: String, default: 'Default Title' }
}
};
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
{ path: '/myPath', component: Page1, props: function(route) { return { title: `${route.path} Title` } } }
]
});
router.push('/myPath');
await router.isReady();
const wrapper = mount(App, {
global: {
plugins: [router, IonicVue]
}
});
const cmp = wrapper.findComponent(Page1);
expect(cmp.props()).toEqual({ title: '/myPath Title' });
});
it('should pass route params as props', async () => {
const Page1 = {
...BasePage,
props: {
title: { type: String, default: 'Default Title' }
}
};
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
{ path: '/:title', component: Page1, props: true }
]
});
router.push('/myPath');
await router.isReady();
const wrapper = mount(App, {
global: {
plugins: [router, IonicVue]
}
});
const cmp = wrapper.findComponent(Page1);
expect(cmp.props()).toEqual({ title: 'myPath' });
});
});