vue-router 如何从父路由继承 props
How to inherit props from parent route with vue-router
我有以下路由器配置,希望将 main.parent
路由的 id
转换为整数,然后传递给子组件(给定 props: true
)所有子组件。
{
path: '/',
component: GrandparentComponent,
name: 'main',
children: [{
path: ':id',
component: ParentComponent,
name: 'main.parent',
props: route => {
return {
// parse URL id to int
id: parseInt(route.params.id, 10)
};
},
children: [{
path: 'details',
name: 'main.parent.child',
component: ChildComponent,
props: true,
children: [{
...
}]
}]
}]
}
然而,似乎 route function 只真正被调用一次(在评估 /:id
时)而不是在评估 /:id/details
时。 vue-router中的相关代码似乎证实了这一点。
const route = routeToDisplay.value;
const matchedRoute = matchedRouteRef.value;
const ViewComponent = matchedRoute && matchedRoute.components[props.name];
// we need the value at the time we render because when we unmount, we
// navigated to a different location so the value is different
const currentName = props.name;
if (!ViewComponent) {
return normalizeSlot(slots.default, { Component: ViewComponent, route });
}
// props from route configuration
const routePropsOption = matchedRoute.props[props.name];
const routeProps = routePropsOption
? routePropsOption === true
? route.params
: typeof routePropsOption === 'function'
? routePropsOption(route)
: routePropsOption
: null;
...
const component = h(ViewComponent, assign({}, routeProps, attrs, {
onVnodeUnmounted,
ref: viewRef,
}));
...
我想知道是否有人试图解决同样的问题以及他们想出了什么解决方案。理想情况下,我想避免为每个子路由重复 props 函数。
Vue Router 中没有这样的功能,可以通过这种方式将 props 传递给 child 路由。
相反,您可以使用 provide
/inject
来有效地做到这一点。 parent 将 provide
id
属性,任何后代都可以 inject
它:
- 在
ParentComponent.vue
中,在 props
上使用 toRefs()
以获得对 id
道具的反应 ref
。
- 使用
provide()
为任何children(包括child路线)提供id
。
- 在
<router-view>
上应用 key
以确保视图是 re-rendered 基于唯一 id
.
- 在
ChildComponent.vue
中,使用 inject
属性注入步骤 2 中的 id
。
// ParentComponent.vue
<script>
/* Composition API */
import { provide, toRefs } from 'vue'
export default {
props: ['id'],
setup(props) {
const { id } = toRefs(props)
provide('id', id)
},
}
/* Options API */
import { toRefs } from 'vue'
export default {
props: ['id'],
provide() {
const { id } = toRefs(this.$props)
return { id }
},
}
</script>
<template>
<router-view :key="id" />
</template>
// ChildComponent.vue
<script>
export default {
inject: ['id'],
}
</script>
<template>
<h2>Detail {{ id }}</h2>
</template>
TL;DR See working demo
我不太明白你在问什么,但我对你的问题的理解是这样的:
- route 函数是否只在父组件上调用一次而不在子组件上调用?
- 如何不为每个子路由重复 props 函数代码
- 如何从父组件继承 props
1:不会,路由函数会在每个子路由上调用。
2:抽象函数代码
您可以创建一个函数并使用它,而不是 copy-pasting 或重复函数代码:
const parseUrlIdtoInt = (route) => ({ id: parseInt(route.params.id, 10) });
// ...
{
path: '...'
props: parseUrlIdtoInt,
children: [
{
path: '...',
props: parseUrlIdtoInt
}
]
}
//...
3: Vue router 向下传递 props
如果在路由器配置中指定了 props
属性,那么 Vue Router 会自动传递 props。
- 使用 props 选项,我们可以将 props 传递给组件
- 使用函数 props 我们可以控制传递什么 prop 的方式
// Router configuration
{
path: '...',
name: '...',
props: true // or a function
// ...
}
你的解决方案
因此,为了在您的 ChildComponent
中访问 id
道具,您可以定义道具并使用它:
作文API
<script setup>
defineProps({ id: Number });
</script>
选项API
<script>
import { defineComponent } from 'vue';
export default defineComponent({
props: {
id: Number,
},
});
</script>
其他non-so-recommended 解决方案
- 如果你不想定义道具,你可以在模板中使用
$attrs.id
访问id。
- 或者您可以使用 Vue Router 中的
useRoute()
函数并访问参数:
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
{{ route.params.id }}
</template>
我有以下路由器配置,希望将 main.parent
路由的 id
转换为整数,然后传递给子组件(给定 props: true
)所有子组件。
{
path: '/',
component: GrandparentComponent,
name: 'main',
children: [{
path: ':id',
component: ParentComponent,
name: 'main.parent',
props: route => {
return {
// parse URL id to int
id: parseInt(route.params.id, 10)
};
},
children: [{
path: 'details',
name: 'main.parent.child',
component: ChildComponent,
props: true,
children: [{
...
}]
}]
}]
}
然而,似乎 route function 只真正被调用一次(在评估 /:id
时)而不是在评估 /:id/details
时。 vue-router中的相关代码似乎证实了这一点。
const route = routeToDisplay.value;
const matchedRoute = matchedRouteRef.value;
const ViewComponent = matchedRoute && matchedRoute.components[props.name];
// we need the value at the time we render because when we unmount, we
// navigated to a different location so the value is different
const currentName = props.name;
if (!ViewComponent) {
return normalizeSlot(slots.default, { Component: ViewComponent, route });
}
// props from route configuration
const routePropsOption = matchedRoute.props[props.name];
const routeProps = routePropsOption
? routePropsOption === true
? route.params
: typeof routePropsOption === 'function'
? routePropsOption(route)
: routePropsOption
: null;
...
const component = h(ViewComponent, assign({}, routeProps, attrs, {
onVnodeUnmounted,
ref: viewRef,
}));
...
我想知道是否有人试图解决同样的问题以及他们想出了什么解决方案。理想情况下,我想避免为每个子路由重复 props 函数。
Vue Router 中没有这样的功能,可以通过这种方式将 props 传递给 child 路由。
相反,您可以使用 provide
/inject
来有效地做到这一点。 parent 将 provide
id
属性,任何后代都可以 inject
它:
- 在
ParentComponent.vue
中,在props
上使用toRefs()
以获得对id
道具的反应ref
。 - 使用
provide()
为任何children(包括child路线)提供id
。 - 在
<router-view>
上应用key
以确保视图是 re-rendered 基于唯一id
. - 在
ChildComponent.vue
中,使用inject
属性注入步骤 2 中的id
。
// ParentComponent.vue
<script>
/* Composition API */
import { provide, toRefs } from 'vue'
export default {
props: ['id'],
setup(props) {
const { id } = toRefs(props)
provide('id', id)
},
}
/* Options API */
import { toRefs } from 'vue'
export default {
props: ['id'],
provide() {
const { id } = toRefs(this.$props)
return { id }
},
}
</script>
<template>
<router-view :key="id" />
</template>
// ChildComponent.vue
<script>
export default {
inject: ['id'],
}
</script>
<template>
<h2>Detail {{ id }}</h2>
</template>
TL;DR See working demo
我不太明白你在问什么,但我对你的问题的理解是这样的:
- route 函数是否只在父组件上调用一次而不在子组件上调用?
- 如何不为每个子路由重复 props 函数代码
- 如何从父组件继承 props
1:不会,路由函数会在每个子路由上调用。
2:抽象函数代码
您可以创建一个函数并使用它,而不是 copy-pasting 或重复函数代码:
const parseUrlIdtoInt = (route) => ({ id: parseInt(route.params.id, 10) });
// ...
{
path: '...'
props: parseUrlIdtoInt,
children: [
{
path: '...',
props: parseUrlIdtoInt
}
]
}
//...
3: Vue router 向下传递 props
如果在路由器配置中指定了 props
属性,那么 Vue Router 会自动传递 props。
- 使用 props 选项,我们可以将 props 传递给组件 - 使用函数 props 我们可以控制传递什么 prop 的方式
// Router configuration
{
path: '...',
name: '...',
props: true // or a function
// ...
}
你的解决方案
因此,为了在您的 ChildComponent
中访问 id
道具,您可以定义道具并使用它:
作文API
<script setup>
defineProps({ id: Number });
</script>
选项API
<script>
import { defineComponent } from 'vue';
export default defineComponent({
props: {
id: Number,
},
});
</script>
其他non-so-recommended 解决方案
- 如果你不想定义道具,你可以在模板中使用
$attrs.id
访问id。 - 或者您可以使用 Vue Router 中的
useRoute()
函数并访问参数:
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
{{ route.params.id }}
</template>