当前位置: 首页 > news >正文

uni-app小程序登录后…

前情

最近新接了一个全新项目,是类似商城的小程序项目,我负责从0开始搭建小程序,我选用的技术栈是uni-app技术栈,其中就有一个用户登录功能,小程序部分页面是需要登录才可以查看的,对于未登录的用户需要引导用户去登录页面,再back回来重新渲染当前页面,以让用户正常使用

思考

问题也不复杂,就是判断登录状态而已,需要登录的页面没登录就引导去登录再回来,回来后再重新渲染页面数据即可

这里有二个动作:一个是判断登录态,一个是重新渲染页面数据,有动作就有触发时机,对于判断登录态,我们是在跳转前判断,还是在跳转进需要登录的页面再判断,对于重新渲染数据当然是进入页面的时候再重新渲染,但是怎么去实现重新渲染了,对于小程序我们第一时间想到的是通过生命钩子来做,那当然就是onShow了

解决方案

基于上述的思考,我想到如下二种解决方案:

请添加图片描述

应该能解决的方案应该有很多,这只是我在实现这个需求的时候想到的二种方案

场景方案1:跳转进需要登录的页面再判断是否是登录态,同时登录回来后通过onShow生命钩子重新渲染页面

此方案优点:就是判断登录态你不需要特定代码去判断,在服务端接口这一块做下处理即可,如果返回状态码是401或者是你和服务端沟通好的错误码时再引导去登录页,这样全局做请求拦截就行,项目中我就是有做这一块的处理,使用的是我封装好的工具方法:常用工具方法 - DCloud 插件市场已分享到插件市场,欢迎使用

此方案的缺点:在未登录的状态下,用户会看到明显的页面跳转,跳转到一个空白页面,突然又跳转到登录页,用户体验不是特别好,同时在onShow生命周期钩子里做数据重新渲染会有一个问题,这样会造成过多的网络请求,如果用户量不小的话会对于服务器造成一些压力

场景方案2:跳转进需要登录的页面前判断登录态,并记录正在跳转的页面,登录后重定向到前面已经记录的跳转页面

此方案优点:避免了onShow频繁触发导致服务器渲染浪费的问题,缺点就是你需要在每一个跳转需要登录的页面前做登录态判断,会导致代码冗余工作量增加,后期维护不是特别好

方案选择

我选择的是场景方案2

二种方案都有优缺点,方案1有一点是用户感受最直接的,就是闪跳的用户体验那一点,至于onShow会导致接口频繁请求问题是有方法解决的,后面会提到;方案2只要想办法解决代码冗余的问题即可

方案实现细节

解决代码冗余问题,我们使用uni-app的拦截api来做下路由拦截即可,根据跳转的URL和当前登录态判断要不要先跳登录页做登录,在main.js中增加路由拦截,关键代码如下:

.../*** 需要登录才能跳转的页面*/
const needLoginPages = ['/orders/detail/detail','/orders/orderList/orderList',...
]// 要拦截的路由方法
const interceptors = ['navigateTo', 'reLaunch', 'redirectTo']
const globalStoreInstance = globalStore(pinia);// 路由拦截
interceptors.forEach(interceptor => {uni.addInterceptor(interceptor, {invoke(e) {// 判断当前页面是否是要需要登录才能跳转的页面里const needLogin = needLoginPages.findIndex(item => e.url.includes(item)) !== -1;if (needLogin && !storage.get(TOKEN)) {// 记录要跳转的页面globalStoreInstance.setNeedLoginBackPage(e.url);uni.navigateTo({url: '/other/login/login'})return false}return true}})
})...

我在写这篇博客的时候,我发现这里代码其实有一个可优化点,你发现了吗?欢迎留言👀讨论

同时在登录页登录成功后需要做一下跳转逻辑,关键代码如下:

...
// 解决登录后跳转的问题
if (globalStoreInstance.needLoginBackPage) {uni.redirectTo({url: globalStoreInstance.needLoginBackPage,complete: () => {globalStoreInstance.setNeedLoginBackPage('');}})
} else {// 解决登录回去页面数据丢失的问题const pages = getCurrentPages();if (pages.length >= 2) {// 获取前一个页面实例const prevPage = pages[pages.length - 2];// 调用前一个页面的onLoad方法if (prevPage?.onLoad) {prevPage.onLoad(prevPage.options || {}); // 传递原始参数}}uni.navigateBack();
}...

看代码除了跳转还处理了back,这一段back逻辑也是我在实现的时候发现它可以解决方案1的onShow问题,也就是说方案1也就是只有一个体验问题,所以二种方案我觉得都是可行的,同时我提供方案1接口拦截的代码:

import { Request, storage } from '@/uni_modules/hbxw-utils/js_sdk/hbxw-utils.js';
import { BASE_URL } from '@/config/http';
import { TOKEN } from '@/config/common';const request = new Request({isLogin: true,
});request.baseUrl = BASE_URL;/*** 请求拦截,可以通过add方法添加多个* 参数为请求配置,可以对请求参数做一些特殊处理*/
request.requestIntercept.add((requestConfig) => {// 如果有传就用传的,没有就去取,为了解决登录默认tokenconsole.log('---- requestConfig ----:', requestConfig)if (!requestConfig.header) {requestConfig.header = {}}// 如果header中没有Accept,则设置为application/jsonif (!requestConfig.header?.Accept) {requestConfig.header.Accept = 'application/json';}if (!requestConfig.header?.Authorization) {let Authorization = ''try {Authorization  = storage.get(TOKEN) || '';} catch (err) {console.log(err)}// 添加Authorization到header中用于服务端登录判断if (Authorization) {if (!requestConfig.header) {requestConfig.header = {}}requestConfig.header.Authorization = Authorization;}}// 如果返回true则请求会中断// return true;
});/*** 响应拦截,可以通过add方法添加多个* 第一个参数为请求响应体* 第二个参数为请求配置信息*/
request.responIntercept.add((response, requestConfig) => {console.log('---- response ----:', response)// 如果接状态码为401,而且当前接口是需要判断登录状态的if (response.statusCode == 401 && requestConfig.isLogin) {uni.navigateTo({url: '/other/login/login'})// 返回true 中断后面处理return true;}// 通用错误处理if (response.statusCode !== 200 || response.data.code !== 200) {uni.showToast({title: response.data.message || '请求失败,请稍后再试',icon: 'none'})return true;}
});export default request;

期望

解决问题的方法千千万,上述是我是解决登录跳转逻辑的处理方案,如果在上面二种方案中,你会选择哪一种了?聪明的你也一定有别的更好的方案,期待你的分享和留言👀,共同进步。

相关文章:

  • Scrapy日志全解析:配置技巧、性能监控与安全审计实战案例
  • 阿里通义万相 Wan2.1-VACE:开启视频创作新境界
  • 从零开始认识 Node.js:异步非阻塞的魅力
  • IP68防水Type-C连接器实测:水下1米浸泡72小时的生存挑战
  • LeetCode 热题 100_寻找重复数(100_287_中等_C++)(技巧)(暴力解法;哈希集合;二分查找)
  • windows下卸载虚拟机VMware(保姆级教程)
  • SQL Server 与 Oracle 常用函数对照表
  • LeetCode 153. 寻找旋转排序数组中的最小值:二分查找法详解及高频疑问解析
  • 一场关于BOM物料清单的深度对话
  • Python训练营打卡Day28
  • 寻找树的中心(重心)
  • 湖北理元理律师事务所:科学债务管理模型构建实录
  • 【JDBC】JDBC常见错误处理方法及驱动的加载
  • C语言:在 Win 10 上,g++ 如何编译 gtk 应用程序
  • linux网络内核的核心函数作用和简介
  • 手写tomcat:基本功能实现(3)
  • Java IO流进阶实战详解(含文件读写、拷贝、加密、字符集)
  • R语言空间数据处理入门教程
  • BC 范式与 4NF
  • AI日报 - 2024年5月17日
  • 网文书单|推荐4本网文,可以当作《绍宋》代餐
  • “先增聘再离任”又添一例,景顺长城基金经理鲍无可官宣辞职
  • 信俗与共:清代新疆回疆儒释道庙宇的中华政教
  • 对谈|“大礼议”:嘉靖皇帝的礼法困境与权力博弈
  • 南昌上饶领导干部任前公示:2人拟提名为县(市、区)长候选人
  • 车建兴被留置:跌落的前常州首富和红星系重整迷路