uni-app三部曲之三: 路由拦截
1.引言
路由拦截,个人理解就是在页面跳转的时候,增加一级拦截器,实现一些自定义的功能,其中最重要的就是判断跳转的页面是否需要登录后查看,如果需要登录后查看且此时系统并未登录,就需要跳转到登录页,登录后跳转到原来想要访问的页面。
2.实现
uni-app的路由跳转分别是uni.navigateTo:保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面;uni.redirectTo:关闭当前页面,跳转到应用内的某个页面;uni.reLaunch:关闭所有页面,打开到应用内的某个页面;uni.switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面;uni.navigateBack:关闭当前页面,返回上一页面或多级页面,可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。
在进行路由跳转时,通过uni.addInterceptor,添加拦截器,实现路由拦截。

拦截是否需要登录的基本思路是通过pages.json文件对应的配置needLogin,进行页面的配置,在拦截时,找到有此配置的所有页面,得到所有页面的路径,和本次访问的路径进行匹配,如果匹配成功,则判断当前是否是登录状态,若没有登录,跳转到登录界面,进行登录。

3.代码
代码主要分为拦截器代码,登录页pages配置,登录页登录按钮功能。
1.拦截器代码
/*** by 菲鸽 on 2024-03-06* 路由拦截,通常也是登录拦截* 可以设置路由白名单,或者黑名单,看业务需要选哪一个* 我这里应为大部分都可以随便进入,所以使用黑名单*/
import { useUserStore } from '@/store'
import { getNeedLoginPages, needLoginPages as _needLoginPages } from '@/utils'
import { getAccessToken } from '@/utils/auth'// 登录页面路径
const loginRoute = '/pages/login/index'const isLogined = () => {const userStore = useUserStore()return userStore.userInfo.isLogin && getAccessToken()
}const isDev = import.meta.env.DEV// 黑名单登录拦截器 - (适用于大部分页面不需要登录,少部分页面需要登录)
const navigateToInterceptor = {// 注意,这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同invoke({ url }: { url: string }) {console.log(url) // /pages/route-interceptor/index?name=feige&age=30const path = url.split('?')[0]let needLoginPages: string[] = []// 为了防止开发时出现BUG,这里每次都获取一下。生产环境可以移到函数外,性能更好if (isDev) {needLoginPages = getNeedLoginPages()} else {needLoginPages = _needLoginPages}const isNeedLogin = needLoginPages.includes(path)if (!isNeedLogin || isLogined()) {return true}const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`console.log(redirectRoute)uni.navigateTo({ url: redirectRoute })return false},
}export const routeInterceptor = {install() {uni.addInterceptor('navigateTo', navigateToInterceptor)uni.addInterceptor('reLaunch', navigateToInterceptor)uni.addInterceptor('redirectTo', navigateToInterceptor)},
}
2.辅助函数代码
import { pages, subPackages, tabBar } from '@/pages.json'
export const getLastPage = () => {// getCurrentPages() 至少有1个元素,所以不再额外判断// const lastPage = getCurrentPages().at(-1)// 上面那个在低版本安卓中打包回报错,所以改用下面这个【虽然我加了src/interceptions/prototype.ts,但依然报错】const pages = getCurrentPages()return pages[pages.length - 1]
}/** 判断当前页面是否是tabbar页 */
export const getIsTabbar = () => {if (!tabBar) {return false}if (!tabBar.list.length) {// 通常有tabBar的话,list不能有空,且至少有2个元素,这里其实不用处理return false}const lastPage = getLastPage()const currPath = lastPage.routereturn !!tabBar.list.find((e) => e.pagePath === currPath)
}/*** 获取当前页面路由的 path 路径 和 redirectPath 路径* path 如 ‘/pages/login/index’* redirectPath 如 ‘/pages/demo/base/route-interceptor’*/
export const currRoute = () => {const lastPage = getLastPage()const currRoute = (lastPage as any).$page// console.log('lastPage.$page:', currRoute)// console.log('lastPage.$page.fullpath:', currRoute.fullPath)// console.log('lastPage.$page.options:', currRoute.options)// console.log('lastPage.options:', (lastPage as any).options)// 经过多端测试,只有 fullPath 靠谱,其他都不靠谱const { fullPath } = currRoute as { fullPath: string }// console.log(fullPath)// eg: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor (小程序)// eg: /pages/login/index?redirect=%2Fpages%2Froute-interceptor%2Findex%3Fname%3Dfeige%26age%3D30(h5)return getUrlObj(fullPath)
}const ensureDecodeURIComponent = (url: string) => {if (url.startsWith('%')) {return ensureDecodeURIComponent(decodeURIComponent(url))}return url
}
/*** 解析 url 得到 path 和 query* 比如输入url: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor* 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}*/
export const getUrlObj = (url: string) => {const [path, queryStr] = url.split('?')// console.log(path, queryStr)if (!queryStr) {return {path,query: {},}}const query: Record<string, string> = {}queryStr.split('&').forEach((item) => {const [key, value] = item.split('=')// console.log(key, value)query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下,可以兼容h5和微信y})return { path, query }
}
/*** 得到所有的需要登录的pages,包括主包和分包的* 这里设计得通用一点,可以传递key作为判断依据,默认是 needLogin, 与 route-block 配对使用* 如果没有传 key,则表示所有的pages,如果传递了 key, 则表示通过 key 过滤*/
export const getAllPages = (key = 'needLogin') => {// 这里处理主包const mainPages = [...pages.filter((page) => !key || page[key]).map((page) => ({...page,path: `/${page.path}`,})),]// 这里处理分包const subPages: any[] = []subPackages.forEach((subPageObj) => {// console.log(subPageObj)const { root } = subPageObjsubPageObj.pages.filter((page) => !key || page[key]).forEach((page: { path: string } & Record<string, any>) => {subPages.push({...page,path: `/${root}/${page.path}`,})})})const result = [...mainPages, ...subPages]// console.log(`getAllPages by ${key} result: `, result)return result
}/*** 得到所有的需要登录的pages,包括主包和分包的* 只得到 path 数组*/
export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map((page) => page.path)/*** 得到所有的需要登录的pages,包括主包和分包的* 只得到 path 数组*/
export const needLoginPages: string[] = getAllPages('needLogin').map((page) => page.path)
3.需要登录页面配置
<route lang="json5">
{style: {navigationBarTitleText: '办公',},needLogin: true,
}
</route>
<template><view class="bg-white overflow-hidden pt-2 px-4"><view>123</view></view>
</template><script setup lang="ts"></script><style lang="scss"></style>
能在组件中配置页面的信息,主要得益于@uni-helper/vite-plugin-uni-pages 插件的功劳,该插件由 uni-helper 官方团队开发,可参考uni 插件 | unibest。
4.登录按钮功能
// 登录系统 一进系统就需要登录
const handleLogin = async () => {const loginRes = await loginApi.login(loginForm)console.log(loginRes)setAccessToken(loginRes.data.accessToken)setRefreshToken(loginRes.data.refreshToken)// 获取路由路径 进行跳转const fullPath = currRoute()console.log(fullPath)uni.redirectTo({ url: fullPath.query.redirect })
}
登录按钮就是获取登录数据,存储token,重定向至原来访问的界面。
4.功能展示
uni-app登录验证
5.写在最后
本文首先感谢unibestuniapp 开发框架,在unibest项目基础上,添加了一些小的功能,基本能满足路由跳转时的拦截,为后续业务的权限管理打下坚实基础。
本文如有疏漏之处,欢迎批评指正。
相关文章:
uni-app三部曲之三: 路由拦截
1.引言 路由拦截,个人理解就是在页面跳转的时候,增加一级拦截器,实现一些自定义的功能,其中最重要的就是判断跳转的页面是否需要登录后查看,如果需要登录后查看且此时系统并未登录,就需要跳转到登录页&…...
专注于国产FPGA芯片研发的异格技术Pre-A+轮融资,博将控股再次投资
近日,苏州异格技术有限公司(以下简称“异格技术”)宣布成功完成数亿元的Pre-A轮融资,由博将控股在参与Pre-A轮投资后,持续投资。这标志着继2022年获得经纬中国、红点中国、红杉中国等机构数亿元天使轮融资后࿰…...
【python】QWidget父子关系,控件显示优先级原理剖析与应用实战演练
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
CTF php RCE(三)
0x07 日志文件包含 判断类型 使用kali curl -I urlF12 打开F12开发者工具,选中之后F5刷新查看server类型即可 配置文件 直接包含或者访问如果有回显就是, NGINX:NGINX 的配置文件通常位于 /etc/nginx/ 目录下,具体的网站配…...
Android 注解的语法原理和使用方法
Android 注解的语法原理和使用方法 关于我 在 Android 开发中,注解(Annotation)是一种强大的工具,用于在代码中添加元数据。注解可以简化代码、提高可读性、减少样板代码,并且在一定程度上增强编译时的类型检查。本文…...
YOLOv10改进 | Conv篇 | 利用FasterBlock二次创新C2f提出一种全新的结构(全网独家首发,参数量下降70W)
一、本文介绍 本文给大家带来的改进机制是利用FasterNet的FasterBlock改进特征提取网络,将其用来改进ResNet网络,其旨在提高计算速度而不牺牲准确性,特别是在视觉任务中。它通过一种称为部分卷积(PConv)的新技术来减少…...
实验-ENSP实现防火墙区域策略与用户管理
目录 实验拓扑 自己搭建拓扑 实验要求 实验步骤 整通总公司内网 sw3配置vlan 防火墙配置IP 配置安全策略(DMZ区内的服务器,办公区仅能在办公时间内(9: 00- 18:00)可以访问,生产区的设备全天可以访问) 配置nat策…...
【游戏客户端】大话slg玩法架构(二)背景地图
【游戏客户端】大话slg玩法架构(二)背景地图 大家好,我是Lampard家杰~~ 今天我们继续给大家分享SLG玩法的实现架构,关于SLG玩法的介绍可以参考这篇上一篇文章:【游戏客户端】制作率土之滨Like玩法 PS:和之前…...
git-工作场景
1. 远程分支为准 强制切换到远程分支并忽略本地未提交的修改 git fetch origin # 获取最新的远程分支信息 git reset --hard origin/feature_server_env_debug_20240604 # 强制切换到远程分支,并忽略本地修改 2. 切换分支 1. **查看所有分支:**…...
coco dataset标签数据结构(json文件)
COCO数据集现在有3种标注类型:object instances(目标实例), object keypoints(目标上的关键点), 和image captions(看图说话),使用json文件存储。 NameImagesLabelstrain linkhttp:…...
GaussDB关键技术原理:高性能(四)
GaussDB关键技术原理:高性能(三)从查询重写RBO、物理优化CBO、分布式优化器、布式执行框架、轻量全局事务管理GTM-lite等五方面对高性能关键技术进行了解读,本篇将从USTORE存储引擎、计划缓存计划技术、数据分区与分区剪枝、列式存…...
总结之企业微信(一)——创建外部群二维码,用户扫码入群
创建外部群 企微接口中没有直接通过服务端API接口创建外部群 可以通过jssdk创建外部群:引用jssdk调用会话接口wx.openEnterpriseChat https://work.weixin.qq.com/api/doc/90000/90136/90511 创建外部群二维码 需要通过企业微信的应用,并且配置客户联…...
透视数据治理:企业如何衡量数据治理的效果?
在企业运营中,各个业务部门的成功与否都是直观且易于量化的,像销售部门卖了多少产品又为企业带来多少盈利,这些都能用具体的数字来说话。但当谈到数据治理的成效时,许多企业与决策者却感到迷茫。 数据治理的重要性不言而喻&#…...
ERC20查询操作--获取ERC20 Token的余额
获取ERC20 Token的余额 https://blog.csdn.net/wypeng2010/article/details/81362562 通过REST查询 curl -X POST --data-binary {"jsonrpc":"2.0","method":"eth_call","params":[{"from": "0x954d1a58c7a…...
Linux运维:MySQL中间件代理服务器,mycat读写分离应用实验
Mycat适用的场景很丰富,以下是几个典型的应用场景: 1.单纯的读写分离,此时配置最为简单,支持读写分离,主从切换 2.分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片 3.多租户应…...
css文字自适应宽度动态出现省略号...
前言 在列表排行榜中通常会出现的一个需求:从左到右依次是名次、头像、昵称、徽标、分数。徽标可能会有多个或者没有徽标,徽标长度是动态的,昵称如果过长要随着有无徽标进行动态截断出现省略号。如下图布局所示(花里胡哨的底色是…...
边缘计算盒子_B100_Jetson Nano (aarch64)开发环境搭建
目录 一、刷机步骤1、搭建刷机环境2、进入刷机模式3、开始刷机 二、系统迁移到TF卡 或者 U盘1、迁移脚本2、提前插入U盘或者TF卡3、 开始迁移 三、搭建miniconda 环境1、下载安装 四、jetpack开发套件环境1、版本查看2、apt 更换国内源3、安装Jetson-stats管理工具 一、刷机步骤…...
【Superset】dashboard 自定义URL
URL设置 在发布仪表盘(dashboard)后,可以通过修改看板属性中的SLUG等,生成url 举例: http://localhost:8090/superset/dashboard/test/ 参数设置 以下 URL 参数可用于修改仪表板的呈现方式:此处参考了官…...
【Linux网络】IP协议{初识/报头/分片/网段划分/子网掩码/私网公网IP/认识网络世界/路由表}
文章目录 1.入门了解2.认识报头3.认识网段4.路由跳转相关指令路由 该文诸多理解参考文章:好文! 1.入门了解 用户需求:将我的数据可靠的跨网络从A主机送到B主机 传输层TCP:由各种方法(流量控制/超时重传/滑动窗口/拥塞…...
香蕉派BPI-Wifi6迷你路由器公开发售
Banana Pi BPI-Wifi6 Mini 公开发售。 Banana Pi BPI-Wifi6 Mini 开源路由器采用Triductor TR6560 TR5220 wifi SOC设计,是一款迷你尺寸的wifi6路由器解决方案。内置高性能双核ARM Cortec A9处理器用于WIFI报文转发或智能业务处理,内置高性能LSW和硬件N…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
