文章目录

  • 深入解析uni-app中的路由拦截方法
  • 路由拦截的重要性
  • uni-app中的路由系统
  • 实现路由拦截的方法
  • 1. 使用页面生命周期钩子
  • 2. 使用全局混入(Mixin)
  • 3. 使用自定义导航守卫
  • 4. 使用条件编译和运行时判断
  • 5. 结合Vuex进行状态管理
  • 路由拦截的最佳实践


深入解析uni-app中的路由拦截方法

在现代移动应用开发中,uni-app因其跨平台能力、高效的编译速度以及基于Vue.js的熟悉性而受到广泛欢迎。随着应用复杂度的增加,路由管理成为了不可或缺的一部分,而路由拦截更是其中的关键环节。本文将详细探讨在uni-app中实现路由拦截的各种方法,并分析其使用场景。

路由拦截的重要性

路由拦截在应用中扮演着守门人的角色,它能够在用户导航至新的页面之前进行必要的检查、修改状态或是获取数据。常见的使用场景包括:

  • 权限验证:确保用户有权访问特定页面。
  • 数据预加载:在进入页面之前预先加载必要的数据。
  • 状态管理:根据应用状态决定是否允许导航,或如何导航。
  • 页面跳转优化:例如,实现页面的按需加载。

uni-app中的路由系统

uni-app中,路由管理是通过框架提供的API来实现的,如uni.navigateTouni.redirectTo等。然而,与传统的Web路由系统不同,uni-app的路由系统是基于原生导航的,因此在实现路由拦截时需要采用特定的方法。

实现路由拦截的方法

1. 使用页面生命周期钩子

uni-app中的每个页面都有其生命周期钩子,如onLoadonShow等。通过在这些钩子中添加逻辑,可以实现简单的路由拦截。

例如,在onLoad钩子中,可以检查用户的登录状态,如果用户未登录,则重定向到登录页面。

export default {
  onLoad() {
    if (!this.$store.state.isLoggedIn) {
      uni.redirectTo({
        url: '/pages/login/login'
      });
    }
  }
}

2. 使用全局混入(Mixin)

如果需要在多个页面中实现相同的拦截逻辑,可以使用Vue的混入功能。创建一个全局混入,并在其中定义生命周期钩子,这样可以在所有页面中应用相同的拦截逻辑。

Vue.mixin({
  onLoad() {
    // 路由拦截逻辑
  }
});

3. 使用自定义导航守卫

虽然uni-app没有像Vue Router那样的导航守卫API,但可以通过封装导航方法来实现类似的功能。

例如,可以创建一个名为navigateTo的封装方法,在该方法中添加拦截逻辑,并在应用中使用此方法替代uni.navigateTo

// 封装导航方法
function navigateTo(url, success, fail) {
  // 拦截逻辑
  if (/* 拦截条件 */) {
    // 处理拦截
  } else {
    uni.navigateTo({
      url,
      success,
      fail
    });
  }
}

// 在应用中使用封装的方法
navigateTo('/pages/target/target');

4. 使用条件编译和运行时判断

在某些场景下,可能需要根据编译条件或运行时环境来决定是否进行路由拦截。uni-app支持条件编译,可以在代码中添加特定平台的逻辑。

export default {
  onLoad() {
    // #ifdef MP-WEIXIN
    // 微信小程序特定逻辑
    // #endif

    // #ifdef H5
    // H5特定逻辑
    // #endif
  }
}

5. 结合Vuex进行状态管理

对于复杂的路由拦截需求,可以结合Vuex进行状态管理。通过在Vuex中定义状态和操作,可以在路由拦截时更方便地访问和修改应用状态。

// 在Vuex store中定义状态
state: {
  isLoggedIn: false
},

// 在页面中使用状态
computed: {
  isLoggedIn() {
    return this.$store.state.isLoggedIn;
  }
},

onLoad() {
  if (!this.isLoggedIn) {
    // 处理拦截
  }
}

路由拦截的最佳实践

  • 保持拦截逻辑的清晰和简洁:避免在拦截逻辑中添加过多的业务代码,以保持其可读性和可维护性。
  • 合理使用异步操作:在拦截逻辑中可能需要执行异步操作(如API调用),要确保正确处理异步操作的结果和错误。
  • 提供友好的用户反馈:在拦截用户导航时,提供明确的反馈,以指导用户进行下一步操作。
  • 考虑性能影响:拦截逻辑可能会对应用性能产生影响,特别是在需要执行复杂操作或多次拦截时。

uni.addInterceptor(STRING, OBJECT) 添加拦截器

STRING 参数说明

需要拦截的api名称,如:uni.addInterceptor('request', OBJECT) ,将拦截 uni.request()

OBJECT 参数说明

参数名

类型

必填

默认值

说明

平台差异说明

invoke

Function


拦截前触发

success

Function


成功回调拦截

fail

Function


失败回调拦截

complete

Function


完成回调拦截

页面跳转的拦截(路由拦截)也就变成拦截 ["navigateTo", "redirectTo", "reLaunch", "switchTab"]这4个方法: 1. 首先创建一个config.js配置一下白名单啥的

export default {
	//不需要登录的页面,白名单
	whiteList: [
		"/pages/index/index",
		//......
	],
	//登录页
	loginPage:"/pages/login/index"
}

2.创建一个init.js

import config from "./config.js"
export default function initApp() {
	/**
	 * 页面跳转拦截器
	 */
	let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];
	list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器
		uni.addInterceptor(item, {
			invoke(e) { // 调用前拦截
				//获取用户的token
				const token = uni.getStorageSync('uni_id_token'),
					//token是否已失效
					tokenExpired = uni.getStorageSync('uni_id_token_expired') < Date.now(),
					//获取要跳转的页面路径(url去掉"?"和"?"后的参数)
					url = e.url.split('?')[0];
				let notNeed = config.whiteList.includes(url)
				// 如果在whiteList里面就不需要登录
				if (notNeed) {
					return e
				} else {
					//需要登录
					if (token == '' || tokenExpired) {
						uni.showToast({
							title: '请先登录',
							icon: 'none'
						})
						uni.navigateTo({
							url: config.loginPage
						})
						return false
					}else{
						return e
					}
				}
				
			},
			fail(err) { // 失败回调拦截 
				console.log(err);
				if (Debug) {
					console.log(err);
					uni.showModal({
						content: JSON.stringify(err),
						showCancel: false
					});
				}
			}
		})
	})
	//添加uniCloud云函数拦截器
	

}