mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
fix(vue): correctly pass route props to components (#22476)
resolves #22472
This commit is contained in:
@ -42,6 +42,7 @@ export interface ViewItem {
|
||||
exact: boolean;
|
||||
registerCallback?: () => void;
|
||||
vueComponentRef: Ref;
|
||||
params?: { [k: string]: any };
|
||||
}
|
||||
|
||||
export interface ViewStacks {
|
||||
|
@ -88,7 +88,8 @@ export const createViewStacks = () => {
|
||||
vueComponentRef: shallowRef(),
|
||||
ionRoute: false,
|
||||
mount: false,
|
||||
exact: routeInfo.pathname === matchedRoute.path
|
||||
exact: routeInfo.pathname === matchedRoute.path,
|
||||
params: routeInfo.params
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -355,15 +355,36 @@ export const IonRouterOutlet = defineComponent({
|
||||
{ ref: 'ionRouterOutlet' },
|
||||
// TODO types
|
||||
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(
|
||||
c.vueComponent,
|
||||
{
|
||||
ref: c.vueComponentRef,
|
||||
key: c.pathname,
|
||||
isInOutlet: true,
|
||||
registerIonPage: (ionPageEl: HTMLElement) => registerIonPage(c, ionPageEl)
|
||||
}
|
||||
)
|
||||
props
|
||||
);
|
||||
})
|
||||
)
|
||||
}
|
||||
|
123
packages/vue/test-app/tests/unit/routing.spec.ts
Normal file
123
packages/vue/test-app/tests/unit/routing.spec.ts
Normal 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' });
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user