Skip to content

Routing Documentation - Route Configuration and Permission Control

Overview

This document details the routing configuration mechanism and permission control system of the VJSP Vue3 framework. The framework adopts a routing architecture based on Vue Router 4, combined with dynamic route generation and fine-grained permission control, providing a complete routing solution for enterprise-level applications.

Routing Architecture

Core Features

  • Dynamic Route Generation: Supports both frontend-controlled and backend-controlled route generation modes
  • Permission Integration: Deep integration of routing with permission system, achieving menu-level and button-level permission control
  • Route Caching: Intelligent route caching mechanism to improve page switching performance
  • Multi-level Route Support: Supports multi-level nested routes with automatic flattening
  • Type Safety: Complete TypeScript type definition support

Technology Stack

  • Vue Router 4: Core routing library
  • Pinia State Management: Route state and permission state management
  • Dynamic Import: Lazy loading of route components to optimize first-screen loading performance
  • Permission Verification: Role-based access control (RBAC)

Route Configuration Mechanism

Routing Modes

The framework supports two route configuration modes:

  1. Frontend Control Mode: Route configuration is completely defined by the frontend, with the permission system responsible for filtering accessible routes
  2. Backend Control Mode: Route structure is returned by the backend, with the frontend dynamically generating routes based on backend data

Route Structure

Constant Routes

Constant routes are basic routes that must be loaded when the application starts, including:

  • Login page
  • 404 error page
  • Redirect routes
  • System basic pages (such as dashboard)

Dynamic Routes

Dynamic routes are generated dynamically based on user permissions, including:

  • Business function module routes
  • System management routes
  • Personal center routes

Route Lazy Loading

The framework uses dynamic imports to implement lazy loading of route components, ensuring component loading safety through the createSafeDynamicImport function:

  • Components loaded on demand to reduce initial bundle size
  • Error boundary handling to prevent loading failures from affecting the application
  • Support for component preloading to enhance user experience

Permission Control Mechanism

Permission Levels

The framework implements three-level permission control:

  1. Route-level Permission: Controls whether users can access specific pages
  2. Menu-level Permission: Controls the display of sidebar menus
  3. Button-level Permission: Controls the display of operation buttons within pages

Permission Verification Process

1. Route Guard Verification

Route guards execute permission verification during each route navigation:

  • Check user login status
  • Verify user permission information
  • Generate accessible dynamic routes
  • Add routes to the router instance

2. Permission Check Functions

The framework provides various permission check functions:

  • hasPermission: Check if specific permission is granted
  • hasAnyPermission: Check if any of the specified permissions are granted
  • hasAllPermissions: Check if all specified permissions are granted

3. Permission Directive

Button-level permission control is implemented through the v-permission directive, supporting various usage patterns and strict permission modes:

Basic Usage
vue
<!-- Single permission check -->
<el-button v-permission="'system:user:add'">Add User</el-button>
<el-button v-permission="'system:user:edit'">Edit User</el-button>

<!-- Multiple permission check (satisfy any one permission) -->
<el-button v-permission="['system:user:add', 'system:user:edit']">
  Add or Edit User
</el-button>
Strict Permission Mode

Strict permission mode is implemented through modifiers, completely removing DOM elements when users lack permissions:

vue
<!-- Strict mode: Remove element when no permission -->
<el-button v-permission.strict="'system:user:delete'">Delete User</el-button>

<!-- Strict mode with multiple permissions -->
<el-button v-permission.strict="['system:user:export', 'system:user:import']">
  Data Import/Export
</el-button>
Permission Directive Features
  • Default Behavior: Disable elements when no permission (reduced opacity, non-clickable)
  • Strict Mode: Use .strict modifier to completely remove elements when no permission
  • Dynamic Updates: Automatically update element state when permissions change
  • Multiple Permission Checks: Support single permission or permission array (satisfy any permission)

Dynamic Route Generation

Frontend Control Mode

In frontend control mode, the route generation process is as follows:

  1. Get user permission list
  2. Filter predefined route configurations
  3. Generate accessible route tree
  4. Add to router instance

Backend Control Mode

In backend control mode, the route generation process is as follows:

  1. Get menu data from backend
  2. Convert menu data to route configuration
  3. Verify route component path validity
  4. Generate and add dynamic routes

Route Utility Functions

Route Generation Tools

The framework provides generateRoutesByFrontEnd and generateRoutesByServer functions to handle route generation for frontend and backend control modes respectively.

Route Processing Tools

  • pathResolve: Path resolution and normalization
  • flatMultiLevelRoutes: Multi-level route flattening
  • isValidRoute: Route configuration validation

Permission Check Tools

  • filterAccessibleRoutes: Filter accessible routes
  • findRouteByPath: Find route by path
  • findRouteByName: Find route by name

Business Module Development Guide (Product Module)

1. Create Route Configuration

Create product.ts route configuration file in src/router/modules/ directory:

typescript
import type { AppRouteRecordRaw } from '@/router/types'

const ProductRoute: AppRouteRecordRaw = {
  path: '/product',
  name: 'Product',
  component: () => import('@/layout/index.vue'),
  meta: {
    title: 'Product Management',
    icon: 'product',
    permission: ['product:view'],
  },
  children: [
    {
      path: 'list',
      name: 'ProductList',
      component: () => import('@/views/modules/product/list.vue'),
      meta: {
        title: 'Product List',
        permission: ['product:list'],
      },
    },
    {
      path: 'add',
      name: 'ProductAdd',
      component: () => import('@/views/modules/product/add.vue'),
      meta: {
        title: 'Add Product',
        permission: ['product:add'],
        hidden: true,
      },
    },
    {
      path: 'edit/:id',
      name: 'ProductEdit',
      component: () => import('@/views/modules/product/edit.vue'),
      meta: {
        title: 'Edit Product',
        permission: ['product:edit'],
        hidden: true,
      },
    },
  ],
}

export default ProductRoute

2. Register Route Module

Import and register product route module in src/router/index.ts:

typescript
import ProductRoute from './modules/product'

// Add to dynamic route configuration
const asyncRoutes: AppRouteRecordRaw[] = [
  // ... other routes
  ProductRoute,
]

3. Create View Components

Create corresponding Vue component files:

src/views/modules/product/list.vue

vue
<template>
  <div class="product-list">
    <SearchForm :fields="searchFields" @search="handleSearch" />

    <DataTable
      :columns="tableColumns"
      :data="productList"
      :loading="loading"
      @refresh="loadProductList"
    >
      <template #action="{ row }">
        <el-button v-permission="'product:edit'" @click="handleEdit(row)"> Edit </el-button>
        <el-button v-permission="'product:delete'" @click="handleDelete(row)"> Delete </el-button>
      </template>
    </DataTable>

    <el-button v-permission="'product:add'" type="primary" @click="handleAdd">
      Add Product
    </el-button>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useProductApi } from '@/api/modules/product'

const router = useRouter()
const productList = ref([])
const loading = ref(false)

const searchFields = [
  { label: 'Product Name', prop: 'productName', type: 'input' },
  { label: 'Product Code', prop: 'productCode', type: 'input' },
]

const tableColumns = [
  { label: 'Product Name', prop: 'productName' },
  { label: 'Product Code', prop: 'productCode' },
  { label: 'Price', prop: 'price' },
  { label: 'Status', prop: 'status' },
]

const loadProductList = async (params = {}) => {
  loading.value = true
  try {
    const response = await useProductApi().getList(params)
    productList.value = response.data.list
  } finally {
    loading.value = false
  }
}

const handleAdd = () => {
  router.push({ name: 'ProductAdd' })
}

const handleEdit = row => {
  router.push({ name: 'ProductEdit', params: { id: row.id } })
}

const handleDelete = async row => {
  // Delete confirmation and operation
}

onMounted(() => {
  loadProductList()
})
</script>

4. Permission Configuration

Configure permission identifiers for product module in permission management system:

  • product:view: View product module
  • product:list: View product list
  • product:add: Add product
  • product:edit: Edit product
  • product:delete: Delete product

Route Caching Mechanism

Route State Management

The framework uses Pinia to manage route state, including:

  • Currently active route
  • Tab route list
  • Sidebar menu state
  • Route cache identifiers

Component Caching

Route component caching is implemented through Vue Router's <keep-alive> and component name attribute:

  • Intelligent cache management to avoid memory leaks
  • Support for maximum cache count limits
  • Manual cache clearing functionality

Route Persistence

Route state is automatically persisted to localStorage, ensuring:

  • Route state is maintained after page refresh
  • Tab state recovery
  • Sidebar expansion state memory

Error Handling

Route Error Handling

The framework implements complete route error handling mechanism:

  • 404 page handling
  • Insufficient permission page
  • Route loading failure handling
  • Network error retry mechanism

Fallback Solution

When dynamic route loading fails, the framework provides fallback solutions:

  • Use static routes as backup
  • Display friendly error messages
  • Provide retry mechanism

Best Practices

Route Naming Convention

  • Use camelCase for route naming
  • Keep route names consistent with component names
  • Use meaningful path structures

Permission Configuration Suggestions

  • Use modular naming for permission identifiers
  • Maintain appropriate permission granularity
  • Regularly clean up unused permissions

Performance Optimization

  • Use route lazy loading appropriately
  • Avoid excessive route nesting
  • Regularly check route configurations

Common Questions

Q: How to add new business module routes?

A: Create route configuration file in src/router/modules/ directory and import/register in main route file.

Q: How to control button-level permissions?

A: Use v-permission directive with corresponding permission identifier.

Q: Route caching not working, what to do?

A: Ensure components have correct name attribute set and check meta.keepAlive setting in route configuration.

Q: How to implement dynamic menus?

A: Use backend control mode, get menu data from backend and convert to route configuration.