Naming Conventions
12.4.1. Route Name Rules
- Route
namemust be written in PascalCase. - Names must be based on the domain entity, combined with a view type suffix to ensure uniqueness.
- Child routes of nested routes must include the parent domain as a prefix.
| View Type | Naming Pattern | Example |
|---|---|---|
| List | {Domain}List | UserList, ProjectList |
| Detail | {Domain}Detail | UserDetail, ProjectDetail |
| Create | {Domain}Create | UserCreate, ProjectCreate |
| Edit | {Domain}Edit | UserEdit, ProjectEdit |
| Settings sub-item | {Parent}{Item} | SettingsProfile, SettingsSecurity |
typescript
// Correct
{ name: 'UserList' }
{ name: 'UserDetail' }
{ name: 'SettingsProfile' }
// Incorrect
{ name: 'user-list' } // kebab-case prohibited
{ name: 'userList' } // camelCase prohibited
{ name: 'Users' } // Missing view type12.4.2. Path Rules
- Route
pathmust be written in kebab-case. - Resource paths must use plural nouns.
- RESTful patterns must be followed; verbs must not be used in place of nouns.
- Dynamic segments must be defined using the
:parameterNameformat.
| Purpose | Path Pattern | Example |
|---|---|---|
| List | /{resource} | /users, /projects |
| Detail | /{resource}/:id | /users/:id |
| Create | /{resource}/new | /users/new |
| Edit | /{resource}/:id/edit | /users/:id/edit |
| Nested resource | /{parent}/:id/{child} | /projects/:id/members |
typescript
// Correct
{ path: '/users' }
{ path: '/users/:id' }
{ path: '/users/new' }
{ path: '/project-members/:id/edit' }
// Incorrect
{ path: '/user' } // Singular form prohibited
{ path: '/getUsers' } // Verb usage prohibited
{ path: '/user_list' } // snake_case prohibited
{ path: '/Users' } // PascalCase prohibited12.4.3. Parameter and Query Naming
- Path parameters must be written in camelCase.
- Query parameters must be written in snake_case.
- A conversion utility should be used for type-safe parameter handling.
typescript
// Path parameters: camelCase
{ path: '/users/:userId/posts/:postId' }
// Query parameters: snake_case
// /users?page_size=20&sort_by=created_attypescript
// src/composables/useTypedRoute.ts
import { computed } from 'vue'
import { useRoute } from 'vue-router'
export function useTypedRoute<
TParams extends Record<string, string> = Record<string, string>,
TQuery extends Record<string, string> = Record<string, string>,
>() {
const route = useRoute()
const typedParams = computed(() => route.params as unknown as TParams)
const typedQuery = computed(() => route.query as unknown as TQuery)
return { params: typedParams, query: typedQuery, route }
}typescript
// Usage example
interface UserDetailParams {
userId: string
}
const { params } = useTypedRoute<UserDetailParams>()
const userId = computed(() => Number(params.value.userId))12.4.4. Programmatic Navigation
- Programmatic navigation must use
nameinstead ofpath. - Name-based navigation is unaffected by path changes, making it easier to maintain.
- In the Composition API, the
useRouteranduseRoutecomposables must be used.
typescript
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// Correct: name-based navigation
router.push({ name: 'UserDetail', params: { id: userId } })
router.replace({ name: 'Login', query: { redirect: route.fullPath } })
// Incorrect: direct path usage (prohibited)
router.push(`/users/${userId}`)
router.push({ path: '/login', query: { redirect: route.fullPath } })- In templates, the same name-based approach must be used.
vue
<template>
<!-- Correct -->
<RouterLink :to="{ name: 'UserDetail', params: { id: user.id } }">
{{ user.name }}
</RouterLink>
<!-- Incorrect -->
<RouterLink :to="`/users/${user.id}`">
{{ user.name }}
</RouterLink>
</template>| Item | Rule |
|---|---|
Route name | PascalCase, domain + view type |
Route path | kebab-case, plural nouns, RESTful |
| Path parameters | camelCase |
| Query parameters | snake_case |
| Navigation method | Name-based required, direct path usage prohibited |
| Composable usage | useRouter, useRoute required |