Dynamic Router
The dynamic routing mechanism of TechUI is the core of the backend management system. It adopts a Backend Control Strategy, meaning the routing table is not hardcoded on the frontend. Instead, based on the current logged-in user's permissions, the backend returns menu data, and the frontend dynamically generates Vue Router configurations by combining this data with the local component registry.
Working Principle
- Component Registration: The frontend maintains a
register.jsfile to map route identifiers (strings) to actual Vue component files. - Fetch Menus: After the user logs in, the menu tree data is retrieved from the backend or a local database.
- Route Matching: The
routerPackagfunction matches thelabelin the menu data with the component registry. - Dynamic Mounting: Matches components are mounted under the parent route named
layoutusingrouter.addRoute. - Global Interception: Logic for page refreshes, authentication, and adding Tabs is handled in
router.beforeEach.
Core Process Analysis
The logic for dynamic routing is mainly concentrated in the global Provider component and is only activated when isActAdminFeatures is true.
Data Persistence and Synchronization
To prevent the loss of Vuex/Pinia state when the page refreshes, TechUI implements a dual persistence mechanism:
- User Info (UserInfo): Watches
$tState.ADMIN.userInfo. Once it changes, it usestStoreCrypto(encrypted storage) to sync to Session/Local Storage. Simultaneously, if the Token or ID is found missing, it automatically triggers a logout. - Menu Data (Menu): Watches
$tState.ADMIN.menu. Once menu data is obtained, it is written to IndexedDB (TuiDB). This ensures that even if the user refreshes the page, the massive menu structure can be quickly restored from the local database without requesting the backend again.
Route Assembly (routerPackag)
routerPackag is the core function that converts business data into route configurations.
// Pseudo-code logic demonstration
async function routerPackag(routerData){
for(let i=0; i<routerData.length; i++){
// 1. Destructure backend data
let { label, icon, title, keepAlive, ... } = routerData[i];
// 2. Look up component in the registry
let comp = $tState.ADMIN.componentRegister[label];
// 3. If it is not a parent node and the component exists
if(!isParent && comp){
// 4. Dynamically add route to the 'layout' parent node
router.addRoute("layout", {
path: '/' + label, // Default path is /label
name: label, // Route name
component: comp, // Corresponding Vue component
meta: { ... } // Inject meta info
});
}
}
}Key Points:
- All dynamic routes are child routes of the
layoutroute. This means they will all be rendered in the<router-view>ofTuiAdminLayout. - The
nameandpathof the route are generated based on thelabelto ensure uniqueness.
Global Route Interception (Guard)
router.beforeEach assumes the role of a "Gatekeeper", handling complex initialization logic:
Phase 1: State Restoration
- User Restoration: If there is no UserID in the state tree, it attempts to read the Token from local storage to restore the login state.
- Menu Restoration: If there is no menu data in the state tree, it attempts to read cached menus from IndexedDB (
TuiDB).
Phase 2: Dynamic Loading
- Initialization Check: Checks the
$ARouterInitedflag. - Execute Loading: If not initialized, calls
routerPackag($AMenu.value)to execute route mounting. - State Flip: After mounting is complete, sets
$ADMIN.value.routerInitedtotrueand re-triggers the route navigation (next({ ...to })) to ensure the new routes take effect.
Phase 3: Business Processing
- Tab Management: If the target route is valid and has a
labelset,tabAdd(to)is automatically called to add it to the top tab bar. - Cache Management: If
meta.keepAliveis true, itsnameis automatically added to the$AKeepAlivelist. - Authentication Failure: If none of the above checks pass (no Token, no ID), it forces a redirect to
/login.
Structure Specification
To work with dynamic routing, the menu data returned by the backend (or local Mock data) should conform to the following JSON structure:
[
{
"label": "dashboard", // Core field: corresponds to the key name in register.js
"title": "Dashboard", // Page title
"icon": "ti-dashboard", // Menu icon
"isParent": false, // Whether it is a parent menu directory
"keepAlive": true, // Whether to enable page caching
"hideInMenu": false, // Whether to hide in the sidebar
"hideInTab": false, // Whether to hide in the Tab bar
"parentId": "root" // Parent node ID
}
]FAQ
Q: Why do I get a 404 after refreshing the page?A: This is usually because the dynamic routes have not finished loading yet. TechUI's beforeEach logic handles this situation: upon refresh, it first restores the menu from IndexedDB and re-registers the routes before executing the jump. If a 404 occurs, please check if IndexedDB has successfully written the menus data.
Q: How do I configure a new page?A: Two steps are required:
- Import the
.vuefile in the frontendregister.jsand export it. - Add the corresponding menu item in the backend (or Mock data), ensuring the
labelmatches the key name inregister.js.