路由组件传参
布尔模式
在你的组件中使用 $route 或 useRoute() 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。虽然这不一定是件坏事,但我们可以通过 props 配置来解除这种行为:
<template>
<div>
User {{ $route.params.id }}
</div>
</template>import User from './User.vue'
// 传入 `createRouter`
const routes = [
{ path: '/users/:id', component: User },
]我们可以通过声明 prop 来在 User.vue 中删除对 $route 的直接依赖:
<!-- User.vue -->
<script setup>
defineProps({
id: String
})
</script>
<template>
<div>
User {{ id }}
</div>
</template>然后我们可以通过设置 props: true 来配置路由将 id 参数作为 prop 传递给组件:
const routes = [
{ path: '/user/:id', component: User, props: true }
]当 props 设置为 true 时,route.params 将被设置为组件的 props。
对象模式
当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。
const routes = [
{
path: '/promotion/from-newsletter',
component: Promotion,
props: { newsletterPopup: false }
}
]函数模式
props支持编写函数:
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。
函数要“无状态”(stateless):函数只依赖当前路由信息计算 props,不依赖组件的响应式状态,否则当状态变化时,props 不会自动更新。如果必须依赖状态,请用“包装组件”来响应式地传递。
假设我们有一个搜索页面:
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]props 函数只在路由变化时调用,如果依赖某个“可变状态”,就不会自动响应。
比如我们希望 props 不仅取决于 route.query.q,还要依赖一个“全局搜索模式”状态(来自 Pinia 或父组件)。 这时候 props: route => (...) 就不行了,因为它不会随着“搜索模式”变化而重新执行。
我们可以写一个包装组件来负责把动态状态传给子组件:
<!-- SearchWrapper.vue -->
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useSearchStore } from '@/stores/searchStore'
import SearchUser from './SearchUser.vue'
const route = useRoute()
const searchStore = useSearchStore()
// 在这里动态计算 props
const props = computed(() => ({
query: route.query.q,
mode: searchStore.mode
}))
</script>
<template>
<SearchUser v-bind="props" />
</template>{
path: '/search',
component: () => import('@/components/SearchWrapper.vue')
}通过 RouterView
你还可以通过 插槽 传递任意参数:
<RouterView v-slot="{ Component }">
<component
:is="Component"
view-prop="value"
/>
</RouterView>在这种情况下,所有视图组件都会接收到 view-prop。通常这并不是一个好主意,因为这意味着所有的视图组件都声明了一个 view-prop prop,但这未必需要。所以请尽可能使用上述的其他选项。
