Skip to content

路由与页面跳转

在uni-app中,路由功能是由框架统一管理的,开发者只需要配置页面路径,并调用相应的API进行页面跳转即可。本文将详细介绍uni-app的路由系统和页面跳转方法。

页面路由配置

uni-app的页面路由全部在pages.json文件中进行配置,包括路径、窗口样式等。

基本配置

json
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/detail/detail",
      "style": {
        "navigationBarTitleText": "详情页"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  }
}

配置说明

  • pages:用于配置页面路径及窗口表现
    • path:页面路径,相对于项目根目录
    • style:页面窗口表现,如导航栏标题、背景色等
  • globalStyle:全局默认的窗口表现

分包配置

对于较大型的应用,可以使用分包加载优化体验:

json
{
  "pages": [
    // 主包页面
  ],
  "subPackages": [
    {
      "root": "pagesA",
      "pages": [
        {
          "path": "list/list",
          "style": { ... }
        }
      ]
    },
    {
      "root": "pagesB",
      "pages": [
        {
          "path": "detail/detail",
          "style": { ... }
        }
      ]
    }
  ]
}

路由跳转方式

uni-app提供了多种页面跳转API,适用于不同的场景。

1. uni.navigateTo(OBJECT)

保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。

javascript
uni.navigateTo({
  url: '/pages/detail/detail?id=1&name=uniapp',
  success: function(res) {
    console.log('跳转成功');
  },
  fail: function(err) {
    console.error('跳转失败', err);
  },
  complete: function() {
    console.log('跳转完成');
  }
});

注意事项

  • 页面栈最多十层,超出会无法跳转
  • url参数中可以携带参数,如?key=value形式

2. uni.redirectTo(OBJECT)

关闭当前页面,跳转到应用内的某个页面。

javascript
uni.redirectTo({
  url: '/pages/detail/detail'
});

使用场景

  • 不希望用户返回上一页时(如登录成功后)
  • 页面栈已经达到最大层级时

3. uni.reLaunch(OBJECT)

关闭所有页面,打开到应用内的某个页面。

javascript
uni.reLaunch({
  url: '/pages/index/index'
});

使用场景

  • 需要重置应用状态时
  • 切换到完全不同的功能模块时

4. uni.switchTab(OBJECT)

跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。

javascript
uni.switchTab({
  url: '/pages/home/home'
});

注意事项

  • 只能跳转到在pages.json中定义的tabBar页面
  • 不能在url中传递参数

5. uni.navigateBack(OBJECT)

关闭当前页面,返回上一页面或多级页面。

javascript
uni.navigateBack({
  delta: 1
});

参数说明

  • delta:返回的页面数,如果 delta 大于现有页面数,则返回到首页

页面传参

传递参数

在跳转页面时,可以通过url参数传递数据:

javascript
uni.navigateTo({
  url: '/pages/detail/detail?id=1&name=uniapp'
});

接收参数

在目标页面的onLoad生命周期函数中接收参数:

javascript
export default {
  onLoad(options) {
    console.log(options.id); // 1
    console.log(options.name); // uniapp
  }
}

路由拦截与导航守卫

uni-app没有提供类似Vue Router的全局导航守卫,但可以通过以下方式实现类似功能:

1. 封装路由方法

javascript
// router.js
export default {
  navigateTo(options) {
    // 在这里添加前置检查逻辑
    if (!getApp().globalData.isLogin && options.url.indexOf('/pages/user/') !== -1) {
      // 未登录且访问需要登录的页面,跳转到登录页
      uni.navigateTo({
        url: '/pages/login/login'
      });
      return;
    }
    
    // 正常跳转
    uni.navigateTo(options);
  }
}

2. 使用混入(mixin)

javascript
// routerMixin.js
export default {
  onShow() {
    // 页面显示时的检查逻辑
    this.checkRoutePermission();
  },
  methods: {
    checkRoutePermission() {
      // 权限检查逻辑
    }
  }
}

然后在页面中使用:

javascript
import routerMixin from '@/mixins/routerMixin';

export default {
  mixins: [routerMixin],
  // 页面其他配置
}

页面栈管理

获取当前页面栈

javascript
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const prevPage = pages[pages.length - 2];

页面栈操作示例

  1. 返回上一页并传值:
javascript
// 在当前页面
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2];
// 直接修改上一页的数据
prevPage.$vm.dataList = newDataList;
// 返回上一页
uni.navigateBack();
  1. 返回指定页面:
javascript
const pages = getCurrentPages();
let pageIndex = -1;

// 查找目标页面在页面栈中的位置
for (let i = 0; i < pages.length; i++) {
  if (pages[i].route === 'pages/target/target') {
    pageIndex = i;
    break;
  }
}

if (pageIndex !== -1) {
  // 计算需要返回的层级
  const delta = pages.length - 1 - pageIndex;
  uni.navigateBack({
    delta: delta
  });
} else {
  // 页面栈中没有目标页面,重新打开
  uni.navigateTo({
    url: '/pages/target/target'
  });
}

最佳实践

1. 统一管理路由

创建一个路由管理文件,集中管理所有页面路径:

javascript
// router.js
export default {
  home: '/pages/index/index',
  detail: '/pages/detail/detail',
  user: '/pages/user/user',
  
  // 带参数的路由方法
  toDetail(id) {
    return `/pages/detail/detail?id=${id}`;
  }
}

使用时:

javascript
import router from '@/utils/router';

// 跳转到详情页
uni.navigateTo({
  url: router.toDetail(123)
});

2. 避免频繁跳转

防止用户快速多次点击导致重复跳转:

javascript
let isNavigating = false;

function navigateTo(url) {
  if (isNavigating) return;
  
  isNavigating = true;
  uni.navigateTo({
    url: url,
    complete: () => {
      setTimeout(() => {
        isNavigating = false;
      }, 500);
    }
  });
}

3. 处理非法参数

在接收页面参数时进行验证:

javascript
export default {
  onLoad(options) {
    const id = options.id;
    
    if (!id) {
      uni.showToast({
        title: '参数错误',
        icon: 'none'
      });
      
      setTimeout(() => {
        uni.navigateBack();
      }, 1500);
      
      return;
    }
    
    // 正常业务逻辑
    this.loadData(id);
  }
}

常见问题

1. 页面栈溢出

当页面层级超过10层时,会出现无法继续跳转的情况。解决方法:

  • 使用 redirectTo 替代 navigateTo
  • 使用 reLaunch 重置页面栈
  • 优化页面结构,减少嵌套层级

2. 参数长度限制

URL参数有长度限制,过长的数据不适合通过URL传递。解决方法:

  • 使用全局状态管理(Vuex/Pinia)
  • 使用本地存储(uni.setStorage)
  • 使用事件总线传递数据

3. 跨平台差异

不同平台对路由的实现有差异,需要注意:

  • H5端支持直接修改window.location,但小程序和App不支持
  • 小程序端页面栈最多10层,App端可能会更多
  • 部分平台对URL长度有严格限制

总结

uni-app的路由系统虽然相对简单,但通过合理的封装和使用,可以满足大多数应用场景的需求。在实际开发中,应根据应用的复杂度选择合适的路由管理方式,并注意处理好页面间的数据传递和页面栈管理。

一次开发,多端部署 - 让跨平台开发更简单