eagleye

Quasar框架路由传参企业级实用教程文档

Quasar框架路由传参企业级实用教程文档

一、Quasar路由基础

Quasar使用Vue Router作为路由系统,路由配置通常在src/router/routes.js中定义,支持参数传递、嵌套路由等企业级特性。

基础路由配置示例

// src/router/routes.js

const routes = [

{

path: '/',

component: () => import('layouts/MainLayout.vue'),

children: [

{

path: 'dashboard',

component: () => import('pages/Dashboard.vue'),

meta: { requiresAuth: true }

},

// 带参数的路由

{

path: 'user/:id',

component: () => import('pages/UserProfile.vue'),

props: true // 关键配置:启用props接收参数

},

// 多参数路由

{

path: 'project/:projectId/task/:taskId',

component: () => import('pages/ProjectTask.vue'),

props: true

}

]

}

]

二、路由传参的三种主要方式

1. 路径参数(Params)

适用场景:必须参数,如ID、标识符等核心业务数据

路由配置

{

path: 'user/:userId',

name: 'UserProfile',

component: () => import('pages/UserProfile.vue'),

props: true // 启用props接收

}

参数传递方式

// 方式1:使用路径字符串

router.push('/user/12345')

// 方式2:使用命名路由(推荐)

router.push({

name: 'UserProfile',

params: { userId: '12345' }

})

组件接收参数

<script setup lang="ts">

// 类型安全的参数接收

defineProps<{

userId: string

}>()

</script>

2. 查询参数(Query)

适用场景:可选参数,如过滤条件、分页信息、排序方式等

参数传递方式

// 方式1:路径字符串

router.push('/search?q=quasar&page=2')

// 方式2:对象形式(推荐)

router.push({

path: '/search',

query: {

q: 'quasar',

page: '2',

filter: 'active'

}

})

组件接收参数

<script setup lang="ts">

import { useRoute } from 'vue-router'

import { computed } from 'vue'

const route = useRoute()

// 响应式查询参数访问

const searchTerm = computed(() => route.query.q as string)

const currentPage = computed(() => parseInt(route.query.page as string || '1'))

</script>

3. Props传参(企业级推荐方式)

适用场景:复杂参数处理,保持组件与路由系统解耦

路由配置

{

path: 'project/:projectId/task/:taskId',

name: 'ProjectTask',

component: () => import('pages/ProjectTask.vue'),

props: (route) => ({

projectId: route.params.projectId,

taskId: route.params.taskId,

viewMode: route.query.mode || 'default', // 合并query参数

isEditMode: route.query.edit === 'true'

})

}

组件接收参数

<script setup lang="ts">

// 定义完整类型接口

interface ProjectTaskProps {

projectId: string

taskId: string

viewMode: 'default' | 'compact' | 'detailed'

isEditMode: boolean

}

// 类型安全接收

const props = defineProps<ProjectTaskProps>()

</script>

三、多参数传递的企业级实践

复杂场景实现:项目任务详情页

需要传递项目ID、任务ID、查看模式和编辑状态等复合参数

路由配置(带参数验证)

{

path: 'project/:projectId/task/:taskId',

name: 'ProjectTaskDetail',

component: () => import('pages/ProjectTaskDetail.vue'),

// 使用路由props函数处理复杂参数

props: (route) => ({

projectId: validateId(route.params.projectId),

taskId: validateId(route.params.taskId),

viewMode: route.query.mode as 'compact' | 'detailed' || 'detailed',

isEditing: route.query.edit === 'true'

})

}

// 参数验证函数

function validateId(id: unknown): string {

if (typeof id === 'string' && /^\d+$/.test(id)) {

return id

}

throw new Error(`Invalid ID: ${id}`)

}

组件实现(完整功能)

<script setup lang="ts">

import { onMounted, watch, computed } from 'vue'

import { useRoute, useRouter } from 'vue-router'

// 定义类型化props

interface TaskDetailProps {

projectId: string

taskId: string

viewMode: 'compact' | 'detailed'

isEditing: boolean

}

const props = defineProps<TaskDetailProps>()

const route = useRoute()

const router = useRouter()

// 更新URL参数的方法

function updateQueryParams(params: Record<string, string>) {

router.push({

name: 'ProjectTaskDetail',

params: {

projectId: props.projectId,

taskId: props.taskId

},

query: {

...route.query,

...params

}

})

}

// 切换编辑模式

function toggleEditMode() {

updateQueryParams({

edit: String(!props.isEditing)

})

}

// 切换视图模式

function setViewMode(mode: 'compact' | 'detailed') {

updateQueryParams({

mode

})

}

// 监听参数变化

watch(

() => [props.projectId, props.taskId],

([newProjectId, newTaskId]) => {

// 重新加载数据

loadTaskData(newProjectId, newTaskId)

},

{ immediate: true } // 初始加载时执行

)

// 初始化加载

onMounted(() => {

loadTaskData(props.projectId, props.taskId)

})

// 数据加载函数

async function loadTaskData(projectId: string, taskId: string) {

// 实际项目中这里会调用API加载数据

console.log(`Loading task ${taskId} from project ${projectId}`)

}

</script>

四、企业级最佳实践

1. 参数验证与类型安全

// 创建参数验证工具函数

import { RouteLocationNormalized } from 'vue-router'

export function parseRouteParams<T>(route: RouteLocationNormalized, validator: (params: any) => T): T {

try {

return validator(route.params)

} catch (error) {

console.error('Invalid route parameters', error)

throw new Error('Invalid route parameters')

}

}

// 使用示例

const taskParamsValidator = (params: any) => {

if (params && typeof params === 'object') {

const p = params as Record<string, unknown>

if (typeof p.projectId === 'string' && typeof p.taskId === 'string') {

return {

projectId: p.projectId,

taskId: p.taskId

}

}

}

throw new Error('Invalid task parameters')

}

// 在组件中使用

const route = useRoute()

const { projectId, taskId } = parseRouteParams(route, taskParamsValidator)

2. 路由守卫中的参数验证

// 在路由守卫中验证参数合法性

router.beforeEach((to, from, next) => {

if (to.name === 'ProjectTaskDetail') {

try {

// 验证项目ID格式

if (!/^PROJ-\d{4}$/.test(to.params.projectId as string)) {

throw new Error('Invalid project ID format')

}

// 验证任务ID存在性(可调用API或状态管理)

if (!taskExists(to.params.projectId, to.params.taskId)) {

return next({ name: 'NotFound' })

}

} catch (error) {

// 记录错误日志

logError(error)

return next({ name: 'InvalidParams' })

}

}

next()

})

3. 复杂对象参数传递方案

// 对象编码工具函数

function encodeObject(obj: Record<string, any>): string {

return btoa(JSON.stringify(obj))

}

function decodeObject<T>(str: string): T {

return JSON.parse(atob(str))

}

// 传递复杂过滤条件

router.push({

path: '/reports',

query: {

filters: encodeObject({

dateRange: ['2023-01-01', '2023-12-31'],

departments: ['finance', 'hr'],

status: 'completed'

})

}

})

// 接收端解码处理

const route = useRoute()

const filters = computed(() => {

try {

return route.query.filters

? decodeObject<ReportFilters>(route.query.filters as string)

: defaultFilters

} catch (e) {

return defaultFilters

}

})

4. 路由参数变化响应式处理

<script setup lang="ts">

import { watch } from 'vue'

import { useRoute } from 'vue-router'

const route = useRoute()

// 监听特定参数变化

watch(

() => route.params.projectId,

(newProjectId) => {

if (newProjectId) {

loadProjectData(newProjectId)

}

},

{ immediate: true } // 立即执行一次

)

// 监听查询参数变化

watch(

() => route.query.view,

(newViewMode) => {

if (newViewMode) {

setViewMode(newViewMode as ViewMode)

}

}

)

</script>

5. 路由状态持久化方案

// 保存路由状态到本地存储

router.afterEach((to) => {

localStorage.setItem('lastRouteState', JSON.stringify({

name: to.name,

params: to.params,

query: to.query

}))

})

// 应用启动时恢复路由状态

const savedRoute = localStorage.getItem('lastRouteState')

if (savedRoute) {

try {

const { name, params, query } = JSON.parse(savedRoute)

router.replace({ name, params, query })

} catch (error) {

console.error('Failed to restore route state', error)

}

}

五、常见问题解决方案

问题1:刷新页面后参数丢失

解决方案:使用路由props代替组件内直接访问$route.params

// 路由配置

{

path: '/user/:userId',

component: UserProfile,

props: true // 关键配置

}

// 组件中

defineProps(['userId']) // 直接使用props

问题2:可选参数处理

解决方案:使用可选参数语法和默认值

// 路由配置

{

path: '/user/:userId/:tab?', // 可选参数

props: (route) => ({

userId: route.params.userId,

tab: route.params.tab || 'profile' // 默认值

})

}

问题3:参数类型转换

解决方案:在props函数中处理类型转换

props: (route) => ({

projectId: Number(route.params.projectId),

page: parseInt(route.query.page as string) || 1,

isActive: route.query.status === 'active'

})

六、企业级路由传参架构图

┌──────────────────────┐ ┌──────────────────────┐

│ 路由配置 │ │ 组件使用 │

│ │ │ │

│ - 路径参数定义 ├───────► defineProps接收 │

│ - props: true │ │ - 类型安全 │

│ - props函数 │ │ - 响应式更新 │

└──────────┬───────────┘ └──────────▲───────────┘

│ │

│ │

│ │

┌──────────▼───────────┐ ┌──────────┴───────────┐

│ 参数传递 │ │ 状态管理 │

│ │ │ │

│ - router.push │ │ - Pinia存储 │

│ - router.replace │ │ - 复杂状态持久化 │

│ - <router-link> │ └──────────────────────┘

└──────────────────────┘

七、企业级路由传参原则总结

1. 优先使用props传递参数:保持组件与路由系统解耦,增强可测试性

2. 严格类型检查:使用TypeScript定义参数接口,确保类型安全

3. 参数验证:在路由守卫和组件中双重验证参数合法性

4. 合理选择传参方式

核心业务数据 → 路径参数(Params)

可选配置信息 → 查询参数(Query)

复杂对象数据 → 状态管理 + URL编码

5. 响应式处理:正确监听参数变化并更新组件状态

6. 状态持久化:关键路由状态本地存储,提升用户体验

通过遵循以上实践,可构建健壮、可维护的企业级Quasar应用路由系统,有效支持各种复杂业务场景的参数传递需求。

 

posted on 2025-08-06 14:16  GoGrid  阅读(10)  评论(0)    收藏  举报

导航