Router
uni-app uses a page-based routing system. Each page corresponds to a Vue component, and routing is managed through configuration and API calls.
Page Route Configuration
pages.json Configuration
All page routes are configured in the pages.json
file:
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "Home"
}
},
{
"path": "pages/about/about",
"style": {
"navigationBarTitleText": "About"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}
Page Path Rules
- Page paths are relative to the project root directory
- The first page in the
pages
array is the application's home page - Page paths do not include file extensions
- Each page must have a corresponding Vue file
Route Navigation
Declarative Navigation
Use the navigator
component for declarative navigation:
<template>
<view>
<!-- Navigate to a page -->
<navigator url="/pages/about/about">Go to About</navigator>
<!-- Navigate with parameters -->
<navigator url="/pages/detail/detail?id=123&name=test">
Go to Detail
</navigator>
<!-- Tab switching -->
<navigator url="/pages/home/home" open-type="switchTab">
Switch to Home Tab
</navigator>
<!-- Redirect (replace current page) -->
<navigator url="/pages/login/login" open-type="redirect">
Go to Login
</navigator>
</view>
</template>
Programmatic Navigation
Use API methods for programmatic navigation:
uni.navigateTo()
Navigate to a new page while keeping the current page in the page stack:
// Basic navigation
uni.navigateTo({
url: '/pages/detail/detail'
});
// Navigation with parameters
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=test',
success: function(res) {
console.log('Navigation successful');
},
fail: function(err) {
console.log('Navigation failed');
}
});
// Navigation with events
uni.navigateTo({
url: '/pages/detail/detail',
events: {
// Listen for data from the opened page
acceptDataFromOpenedPage: function(data) {
console.log(data);
}
},
success: function(res) {
// Send data to the opened page
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'from opener page' });
}
});
uni.redirectTo()
Close the current page and navigate to a new page:
uni.redirectTo({
url: '/pages/login/login'
});
uni.reLaunch()
Close all pages and navigate to a new page:
uni.reLaunch({
url: '/pages/home/home'
});
uni.switchTab()
Switch to a tab page:
uni.switchTab({
url: '/pages/home/home'
});
uni.navigateBack()
Navigate back to the previous page:
// Go back one page
uni.navigateBack();
// Go back multiple pages
uni.navigateBack({
delta: 2 // Go back 2 pages
});
Parameter Passing
URL Parameters
Pass parameters through URL query strings:
// Sender page
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=test&type=product'
});
// Receiver page
export default {
onLoad(options) {
console.log(options.id); // 123
console.log(options.name); // test
console.log(options.type); // product
}
}
Event Channel Communication
Use event channels for complex data passing:
// Sender page
uni.navigateTo({
url: '/pages/detail/detail',
events: {
// Listen for data from the opened page
acceptDataFromOpenedPage: function(data) {
console.log('Received data:', data);
},
someEvent: function(data) {
console.log('Some event triggered:', data);
}
},
success: function(res) {
// Send data to the opened page
res.eventChannel.emit('acceptDataFromOpenerPage', {
user: { id: 1, name: 'John' },
products: [1, 2, 3]
});
}
});
// Receiver page
export default {
onLoad() {
// Get event channel
const eventChannel = this.getOpenerEventChannel();
// Listen for data from opener page
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log('Received data from opener:', data);
});
// Send data back to opener page
eventChannel.emit('acceptDataFromOpenedPage', { result: 'success' });
}
}
Route Interception
Global Route Interception
Intercept route navigation globally:
// main.js
import { createSSRApp } from 'vue'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
// Add route interception
const originalNavigateTo = uni.navigateTo;
uni.navigateTo = function(options) {
// Check login status
const token = uni.getStorageSync('token');
if (!token && options.url.includes('/pages/user/')) {
// Redirect to login if not authenticated
return originalNavigateTo({
url: '/pages/login/login'
});
}
return originalNavigateTo(options);
};
return {
app
}
}
Page-level Route Guards
Implement route guards at the page level:
export default {
onLoad() {
// Check permissions before page loads
this.checkPermissions();
},
methods: {
checkPermissions() {
const userRole = uni.getStorageSync('userRole');
if (userRole !== 'admin') {
uni.showToast({
title: 'Access denied',
icon: 'none'
});
uni.navigateBack();
}
}
}
}
Page Stack Management
Understanding Page Stack
uni-app maintains a page stack to manage page navigation:
navigateTo
: Pushes a new page onto the stackredirectTo
: Replaces the current pagenavigateBack
: Pops pages from the stackreLaunch
: Clears the stack and pushes a new pageswitchTab
: Special handling for tab pages
Page Stack Limits
Different platforms have different page stack limits:
- Mini Programs: Maximum 10 pages
- App: No strict limit, but too many pages may affect performance
- H5: Depends on browser memory
Managing Page Stack
// Get current page stack
const pages = getCurrentPages();
console.log('Current page count:', pages.length);
console.log('Current page:', pages[pages.length - 1]);
// Check if can go back
if (pages.length > 1) {
uni.navigateBack();
} else {
uni.reLaunch({
url: '/pages/home/home'
});
}
Tab Bar Navigation
Tab Bar Configuration
Configure tab bar in pages.json
:
{
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/home/home",
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png",
"text": "Home"
},
{
"pagePath": "pages/category/category",
"iconPath": "static/category.png",
"selectedIconPath": "static/category-active.png",
"text": "Category"
},
{
"pagePath": "pages/user/user",
"iconPath": "static/user.png",
"selectedIconPath": "static/user-active.png",
"text": "Profile"
}
]
}
}
Tab Bar Navigation
// Switch to tab page
uni.switchTab({
url: '/pages/home/home'
});
// Programmatically set tab bar badge
uni.setTabBarBadge({
index: 1,
text: '3'
});
// Remove tab bar badge
uni.removeTabBarBadge({
index: 1
});
Dynamic Routing
Dynamic Route Parameters
Handle dynamic route parameters:
// Navigate with dynamic parameters
const userId = 123;
uni.navigateTo({
url: `/pages/user/profile?userId=${userId}`
});
// Handle dynamic parameters
export default {
data() {
return {
userId: null,
userInfo: null
}
},
onLoad(options) {
this.userId = options.userId;
this.loadUserInfo();
},
methods: {
async loadUserInfo() {
try {
const res = await this.$http.get(`/api/users/${this.userId}`);
this.userInfo = res.data;
} catch (error) {
console.error('Failed to load user info:', error);
}
}
}
}
Route Animation
Custom Page Transitions
Configure page transition animations:
{
"pages": [
{
"path": "pages/detail/detail",
"style": {
"navigationBarTitleText": "Detail",
"animationType": "slide-in-right",
"animationDuration": 300
}
}
]
}
Programmatic Animations
uni.navigateTo({
url: '/pages/detail/detail',
animationType: 'slide-in-bottom',
animationDuration: 200
});
Best Practices
1. Route Organization
// Create a route helper
class RouteHelper {
static navigateToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
});
}
static navigateToUser(userId) {
uni.navigateTo({
url: `/pages/user/profile?userId=${userId}`
});
}
static goBack(delta = 1) {
const pages = getCurrentPages();
if (pages.length > delta) {
uni.navigateBack({ delta });
} else {
uni.reLaunch({
url: '/pages/home/home'
});
}
}
}
// Usage
RouteHelper.navigateToDetail(123);
2. Parameter Validation
export default {
onLoad(options) {
// Validate required parameters
if (!options.id) {
uni.showToast({
title: 'Invalid parameters',
icon: 'none'
});
uni.navigateBack();
return;
}
this.loadData(options.id);
}
}
3. Error Handling
const navigateWithErrorHandling = (options) => {
uni.navigateTo({
...options,
fail: (err) => {
console.error('Navigation failed:', err);
uni.showToast({
title: 'Navigation failed',
icon: 'none'
});
}
});
};
4. Deep Linking Support
// Handle deep links
export default {
onLaunch(options) {
// Handle app launch from deep link
if (options.path) {
this.handleDeepLink(options.path, options.query);
}
},
methods: {
handleDeepLink(path, query) {
// Parse and navigate to the appropriate page
const url = this.buildUrl(path, query);
uni.reLaunch({ url });
},
buildUrl(path, query) {
const queryString = Object.keys(query)
.map(key => `${key}=${query[key]}`)
.join('&');
return queryString ? `${path}?${queryString}` : path;
}
}
}
Platform Differences
Mini Program Limitations
// #ifdef MP
// Mini program specific route handling
if (getCurrentPages().length >= 10) {
// Redirect instead of navigate when stack is full
uni.redirectTo({
url: '/pages/detail/detail'
});
} else {
uni.navigateTo({
url: '/pages/detail/detail'
});
}
// #endif
// #ifdef H5
// H5 specific route handling
uni.navigateTo({
url: '/pages/detail/detail'
});
// #endif
App-specific Features
// #ifdef APP-PLUS
// App-specific route animations
uni.navigateTo({
url: '/pages/detail/detail',
animationType: 'slide-in-right',
animationDuration: 300
});
// #endif
This routing system provides a comprehensive solution for navigation in uni-app applications, supporting various navigation patterns and platform-specific optimizations.