mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +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;
|
exact: boolean;
|
||||||
registerCallback?: () => void;
|
registerCallback?: () => void;
|
||||||
vueComponentRef: Ref;
|
vueComponentRef: Ref;
|
||||||
|
params?: { [k: string]: any };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ViewStacks {
|
export interface ViewStacks {
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
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