Quasar 路由 Props 传参:企业级应用指南
Quasar 路由 Props 传参:企业级应用指南
一、两种传参方式核心对比
|
特性 |
props: true |
props: route => ({}) |
|
参数来源 |
仅路径参数 (params) |
路径参数 + 查询参数 (query) |
|
映射方式 |
自动映射同名 prop |
手动自定义映射 |
|
类型转换 |
❌ 不支持 |
✅ 支持 (字符串→数字/布尔等) |
|
默认值设置 |
❌ 不支持 |
✅ 支持 |
|
参数重命名 |
❌ 不支持 |
✅ 支持 |
|
企业级适用性 |
简单场景 |
复杂场景 (推荐) |
二、props: true基础用法
1. 路由配置
// src/router/routes.ts
{
path: '/user/:userId',
component: () => import('pages/UserProfile.vue'),
props: true // 自动映射路径参数到组件 props
}
2. 组件接收
// pages/UserProfile.vue
const props = defineProps<{
userId: string // 与路由参数同名
}>()
// 使用
console.log(props.userId) // 直接访问路径参数
3. 适用场景
- 单一ID参数传递(如/product/:id)
- 参数名与组件prop名完全一致
- 无需处理查询参数的简单页面
三、props: route => ({})高级用法
1. 基础多参数映射
// 路由配置
{
path: '/profile/:userId',
component: UserProfile,
props: route => ({
// 路径参数
userId: route.params.userId,
// 查询参数 + 默认值
viewMode: route.query.mode || 'standard',
// 类型转换
isEditing: route.query.edit === 'true',
// 复杂计算
accessLevel: getUserAccess(route.params.userId)
})
}
// 组件接收
const props = defineProps<{
userId: string
viewMode: 'standard' | 'compact'
isEditing: boolean
accessLevel: 'read' | 'write' | 'admin'
}>()
2. 企业级参数处理封装
// utils/routeParams.ts
export function processParams(route: RouteLocationNormalized) {
return {
// 参数验证
projectId: validateProjectId(route.params.projectId),
// 类型转换 + 默认值
page: parseInt(route.query.page as string) || 1,
// 枚举验证
sortBy: ['name', 'date', 'size'].includes(route.query.sort as string)
? route.query.sort
: 'date',
// 复杂对象解析
filters: route.query.filters
? JSON.parse(decodeURIComponent(route.query.filters as string))
: {}
}
}
// 路由配置中使用
{
path: '/projects/:projectId',
component: ProjectDashboard,
props: route => processParams(route)
}
四、企业级最佳实践
1. 参数验证策略
// 验证函数示例
function validateUserId(userId: unknown): string {
if (typeof userId !== 'string' || !/^[A-Z0-9]{32}$/.test(userId)) {
throw new Error(`Invalid user ID: ${userId}`)
}
return userId
}
// 路由配置中集成
props: route => ({
userId: validateUserId(route.params.userId),
// 其他参数...
})
2. 多场景传参方案
场景A:电商产品列表
{
path: '/products',
component: ProductList,
props: route => ({
category: route.query.category || 'all',
sort: {
by: route.query.sortBy || 'price',
order: route.query.order === 'desc' ? 'desc' : 'asc'
},
pagination: {
page: parseInt(route.query.page as string) || 1,
limit: parseInt(route.query.limit as string) || 20
}
})
}
场景B:数据可视化仪表板
{
path: '/analytics/:dashboardId',
component: AnalyticsDashboard,
props: route => ({
dashboardId: route.params.dashboardId,
dateRange: {
start: route.query.startDate as string,
end: route.query.endDate as string
},
metrics: route.query.metrics
? (route.query.metrics as string).split(',')
: ['revenue', 'users']
})
}
3. 类型安全增强
// types/route.ts
export interface ProductListProps {
category: string
sort: {
by: 'price' | 'rating' | 'date'
order: 'asc' | 'desc'
}
pagination: {
page: number
limit: number
}
}
// 组件中使用
import type { ProductListProps } from '@/types/route'
const props = defineProps<ProductListProps>()
五、常见问题解决方案
1. 参数刷新丢失
问题:页面刷新后查询参数丢失
方案:通过路由props注入而非直接读取$route
// ✅ 正确:通过props接收
const props = defineProps<{ tab: string }>()
// ❌ 错误:直接依赖$route
const tab = ref(route.query.tab) // 刷新后需手动同步
2. 复杂对象传递
方案:使用JSON序列化+URL编码
// 传递端
const filters = { price: [100, 500], tags: ['new'] }
router.push({
path: '/products',
query: { filters: encodeURIComponent(JSON.stringify(filters)) }
})
// 接收端
props: route => ({
filters: route.query.filters
? JSON.parse(decodeURIComponent(route.query.filters as string))
: {}
})
3. 参数变更响应
// 监听props变化
watch(
() => props.userId,
(newId) => {
fetchUserData(newId) // 参数变化时重新加载数据
},
{ immediate: true } // 初始加载时执行
)
六、企业级架构建议
1. 参数处理分层
路由层 → 参数验证层 → 组件层
↓ ↓ ↓
路径/查询 → 验证/转换 → 类型化props
2. 工具函数封装
// composables/useRouteParams.ts
export function useRouteParams() {
const router = useRouter()
return {
// 安全更新查询参数
updateQuery: (params: Record<string, any>) => {
router.push({
...router.currentRoute.value,
query: { ...router.currentRoute.value.query, ...params }
})
}
}
}
3. 性能优化
- 避免在props函数中执行复杂计算
- 对大型数据集使用shallowRef
- 使用Object.freeze()冻结静态默认值
七、最佳实践总结
1. 优先选择函数形式:props: route => ({})提供完整控制能力
2. 全面参数验证:对所有外部输入进行类型和格式校验
3. 类型系统集成:使用TypeScript接口定义props结构
4. 默认值全覆盖:为所有可选参数提供合理默认值
5. 避免直接依赖$route:通过props注入实现组件解耦
6. 复杂逻辑封装:将参数处理逻辑提取为独立工具函数
通过以上规范,可构建类型安全、可维护、抗异常的企业级路由参数系统,同时兼顾开发效率与代码质量。
浙公网安备 33010602011771号