位置: IT常识 - 正文

uni-app 怎么实现路由拦截(uni-app 怎么实现页面不跳转依旧可以传数据)

编辑:rootadmin
uni-app 怎么实现路由拦截 前言

推荐整理分享uni-app 怎么实现路由拦截(uni-app 怎么实现页面不跳转依旧可以传数据),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:uniapp怎么实现扫描图片信息后自动填充,uniapp怎么实现支付,uniapp怎么实现扫描图片信息后自动填充,uniapp怎么实现app关闭后接收信息,uniapp怎么实现app关闭后接收信息,uniapp怎么实现多端兼容,uniapp怎么实现扫描图片信息后自动填充,uniapp怎么实现支付,内容如对您有帮助,希望把文章链接给更多的朋友!

随着业务的需求,项目需要支持H5、各类小程序以及IOS和Android,这就需要涉及到跨端技术,不然每一端都开发一套,人力成本和维护成本太高了。团队的技术栈主要以Vue为主,最终的选型是以uni-app+uview2.0作为跨端技术栈。以前一直听别人吐槽uni-app怎么怎么不好,但是没什么概念,这一次需要为团队开发一个项目的基础框架和一些示例页面,主要是支持路由拦截、http请求多实例、请求数据加密以及登录功能封装,发现uni-app的生态不怎么健全,比如我们项目很需要的路由拦截,http请求拦截,这些都没有提供,对于跨端的兼容问题也挺多的。这篇文章聊聊的路由拦截的调研,以及最终的选择和实现。

实现路由拦截的方式使用uni-simple-router重写uni-app跳转方法对uni-app跳转方法做进一步的封装使用uni-simple-router

uni-simple-router是为uni-app专门提供的路由管理器,使用方式跟vue-router的API一致,可以很方便的上手,Github 也有了六百多的start,它可以说是uni-app用来做路由管理很好的选择,但是我没有选择使用它,个人认为开发h5是可以的,但是如果做跨端,可能会有一些后患,接下来我们聊聊为什么不使用它的原因。

无法拦截switchTab、navigateBack

这个其实也不算是一个缺点,目前也没找到可以拦截这两个事件的路由插件,如果确实需要实现这两种跳转方式的拦截,也是可以实现的,可以使用下一种方式,对这两种方法进行暴力重写。

没有解决全部的跨端兼容问题

这个其实是我不选择它的主要原因,根据官方文档的说明,根据文档去配置和编写,基本上能解决所有端上的95%的问题,其他的5%的问题需要去查看编译到端的说明。代码还是严谨的,缺少1%都是不完美的,更何况是5%。这会导致在以后的使用过程中,可能因为兼容问题,导致自己没办法去解决,或者为了解决这个问题,需要花费大量的时间和精力,有可能得不偿失。

编译app时,不能用’nvue’作为启动页面

nvue 不能直接作为启动页面。因为在启动时 uni-app 会检测启动页面是否为原生渲染,原生渲染时不会执行路由跳转,插件无法正确捕捉页面挂载。这也是一个问题,我们可以尽量的去避免,但以后有未知的情况,可能我们的启动页必须就是以nvue来实现。

暴力重写uni-app跳转方法

这种方式虽然有点简单粗暴,但是效果挺好的,代码也很简短,Vue2.0对于数组的响应式监听也是采用这种方式。虽然实现了,但可能有些同学不知道怎么使用,直接把这段代码写在main.js就可以了,或者也可以在单独的文件里封装一个封装一个函数,然后在main.js引入,然后执行该方法。

const routeInterceptor = () => {const methodToPatch = ["navigateTo", "redirectTo", "switchTab", "navigateBack"];methodToPatch.map((type) => {// 通过遍历的方式分别取出,uni.navigateTo、uni.redirectTo、uni.switchTab、uni.navigateBack// 并且对相应的方法做重写const original = uni[type];uni[item] = function (options = {}) {if (!token) {// 判断是否存在token,不存在重定向到登录页uni.navigateTo({url: "/login",});} else {return original.call(this, opt);}};});}routeInterceptor()

这是一个最极简的方式,需要添加其他参数和判断逻辑,大家可以自行添加,这里只是抛砖引玉,给大家提供一个思路。

使用方式handleDetail() {uni.navigateTo({ url: '/detail?id=11111111111'})} 对uni-app跳转方法做进一步的封装

这个是 uView提供的一种路由封装方式,对于路由传参做了进一步的封装,使用起来更加方便,但是不涉及到uni-app跳转方式的重写,所以也谈不上改了路由跳转的跨端兼容,所以还是具有uni-app一致的兼容性。但是官方文档没有说明提供了路由拦截,但这个还是我们特别需要的功能,去查看源码,发现还是提供了这个功能。现在还存在的一个问题是,这个功能是跟uView强耦合的,可能我们并不想使用uView,所以我们可以将这个功能独立抽离。

uni-app 怎么实现路由拦截(uni-app 怎么实现页面不跳转依旧可以传数据)

目录结构

/router/index.js

这个文件主要提供路由拦截函数,具体的实现,可以大家可以根据自己的需求实现,最后向外暴露一个包含install方法的对象,使用的时候可以直接用Vue.use进行注册。

routeConfig这个参数是路由相关的配置,resolve 传递一个true或者false表示是否允许跳转。

routeConfig属性参数名类型默认值是否必填说明typeStringnavigateTofalsenavigateTo或to对应uni.navigateTo,redirect或redirectTo对应uni.redirectTo,switchTab或tab对应uni.switchTab,reLaunch对应uni.reLaunch,navigateBack或back对应uni.navigateBackurlString-falsetype为navigateTo,redirectTo,switchTab,reLaunch时为必填deltaNumber1falsetype为navigateBack时用到,表示返回的页面数paramsObject-false传递的对象形式的参数,如{name: ‘lisa’, age: 18}animationTypeStringpop-infalse只在APP生效,详见窗口动画(opens new window)animationDurationNumber300false动画持续时间,单位msimport route from "./route";// 配置白名单const whiteList = ["/pages/login/index"];const install = function (Vue, options) {uni.$e = { route };Vue.prototype.route = route;uni.$e.routeIntercept = (routeConfig, resolve) => {const path = routeConfig.url.split("?")[0];if (!whiteList.includes(path) && !uni.getStorageSync("token")) {uni.$e.route("/pages/login/index");return;}resolve(true);};};export default {install,}; /router/route.js

这个文件,主要是对于uni-app跳转做了封装,主要做的还是传参部分,实现跟vue-router一致的传参方式,使用起来更加方便优雅,同时提供一个uni.$e.routeIntercept路由拦截方法。

/** * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷 * 并且带有路由拦截功能 */import { queryParams, deepClone, deepMerge, page } from "./utils";class Router {constructor() {// 原始属性定义this.config = {type: "navigateTo",url: "",delta: 1, // navigateBack页面后退时,回退的层数params: {}, // 传递的参数animationType: "pop-in", // 窗口动画,只在APP有效animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效intercept: false, // 是否需要拦截};// 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文// 这里在构造函数中进行this绑定this.route = this.route.bind(this);}// 判断url前面是否有"/",如果没有则加上,否则无法跳转addRootPath(url) {return url[0] === "/" ? url : `/${url}`;}// 整合路由参数mixinParam(url, params) {url = url && this.addRootPath(url);// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"// 如果有url中有get参数,转换后无需带上"?"let query = "";if (/.*\/.*\?.*=.*/.test(url)) {// object对象转为get类型的参数query = queryParams(params, false);// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开return (url += `&${query}`);}// 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号query = queryParams(params);return (url += query);}// 对外的方法名称async route(options = {}, params = {}) {// 合并用户的配置和内部的默认配置let mergeConfig = {};if (typeof options === "string") {// 如果options为字符串,则为route(url, params)的形式mergeConfig.url = this.mixinParam(options, params);mergeConfig.type = "navigateTo";} else {mergeConfig = deepClone(options, this.config);// 否则正常使用mergeConfig中的url和params进行拼接mergeConfig.url = this.mixinParam(options.url, options.params);}// 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题if (mergeConfig.url === page()) return;if (params.intercept) {this.config.intercept = params.intercept;}// params参数也带给拦截器mergeConfig.params = params;// 合并内外部参数mergeConfig = deepMerge(this.config, mergeConfig);// 判断用户是否定义了拦截器if (typeof uni.$e.routeIntercept === "function") {// 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转const isNext = await new Promise((resolve, reject) => {uni.$e.routeIntercept(mergeConfig, resolve);});// 如果isNext为true,则执行路由跳转isNext && this.openPage(mergeConfig);} else {this.openPage(mergeConfig);}}// 执行路由跳转openPage(config) {// 解构参数const { url, type, delta, animationType, animationDuration } = config;if (config.type == "navigateTo" || config.type == "to") {uni.navigateTo({url,animationType,animationDuration,});}if (config.type == "redirectTo" || config.type == "redirect") {uni.redirectTo({url,});}if (config.type == "switchTab" || config.type == "tab") {uni.switchTab({url,});}if (config.type == "reLaunch" || config.type == "launch") {uni.reLaunch({url,});}if (config.type == "navigateBack" || config.type == "back") {uni.navigateBack({delta,});}}}export default new Router().route; /router/uitls.js

这个文件主要是为路由封装提供一些工具函数

/** * @description 对象转url参数 * @param {object} data,对象 * @param {Boolean} isPrefix,是否自动加上"?" * @param {string} arrayFormat 规则 indices|brackets|repeat|comma */export const queryParams = ( data = {},isPrefix = true,arrayFormat = "brackets" ) => {const prefix = isPrefix ? "?" : "";const _result = [];if (["indices", "brackets", "repeat", "comma"].indexOf(arrayFormat) == -1)arrayFormat = "brackets";for (const key in data) {const value = data[key];// 去掉为空的参数if (["", undefined, null].indexOf(value) >= 0) {continue;}// 如果值为数组,另行处理if (value.constructor === Array) {// e.g. {ids: [1, 2, 3]}switch (arrayFormat) {case "indices":// 结果: ids[0]=1&ids[1]=2&ids[2]=3for (let i = 0; i < value.length; i++) {_result.push(`${key}[${i}]=${value[i]}`);}break;case "brackets":// 结果: ids[]=1&ids[]=2&ids[]=3value.forEach((_value) => {_result.push(`${key}[]=${_value}`);});break;case "repeat":// 结果: ids=1&ids=2&ids=3value.forEach((_value) => {_result.push(`${key}=${_value}`);});break;case "comma":// 结果: ids=1,2,3let commaStr = "";value.forEach((_value) => {commaStr += (commaStr ? "," : "") + _value;});_result.push(`${key}=${commaStr}`);break;default:value.forEach((_value) => {_result.push(`${key}[]=${_value}`);});}} else {_result.push(`${key}=${value}`);}}return _result.length ? prefix + _result.join("&") : "";};/** * 是否数组 */function isArray(value) {if (typeof Array.isArray === "function") {return Array.isArray(value);}return Object.prototype.toString.call(value) === "[object Array]";}/** * @description 深度克隆 * @param {object} obj 需要深度克隆的对象 * @returns {*} 克隆后的对象或者原值(不是对象) */export const deepClone = (obj) => {// 对常见的“非”值,直接返回原来值if ([null, undefined, NaN, false].includes(obj)) return obj;if (typeof obj !== "object" && typeof obj !== "function") {// 原始类型直接返回return obj;}const o = isArray(obj) ? [] : {};for (const i in obj) {if (obj.hasOwnProperty(i)) {o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];}}return o;};/** * @description JS对象深度合并 * @param {object} target 需要拷贝的对象 * @param {object} source 拷贝的来源对象 * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象) */export const deepMerge = (target = {}, source = {}) => {target = deepClone(target);if (typeof target !== "object" || typeof source !== "object") return false;for (const prop in source) {if (!source.hasOwnProperty(prop)) continue;if (prop in target) {if (typeof target[prop] !== "object") {target[prop] = source[prop];} else if (typeof source[prop] !== "object") {target[prop] = source[prop];} else if (target[prop].concat && source[prop].concat) {target[prop] = target[prop].concat(source[prop]);} else {target[prop] = deepMerge(target[prop], source[prop]);}} else {target[prop] = source[prop];}}return target;};/** * @description 获取当前页面路径 */export const page = () => {const pages = getCurrentPages();// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组return `/${pages[pages.length - 1]?.route ?? ""}`;}; 路由配置

在main.js引入

import router from "./router";Vue.use(router); 使用方式

更全的使用方式可以查看 uView路由跳转文档

全局使用uni.$e.route('/pages/info/index');vue文件中使用this.route('/pages/info/index');拦截switchTab、navigateBack

现在的方式还是没办法支持拦截switchTab、navigateBack,所以需要借助第二种方式,重写这两种方法,具体实现,完善 /router/index.js

// /router/index.jsimport route from "./route";// 配置白名单const whiteList = ["/pages/login/index"];const handleOverwirteRoute = () => {// 重写switchTab、navigateBackconst methodToPatch = ["switchTab", "navigateBack"];methodToPatch.map((type) => {// 通过遍历的方式分别取出,uni.switchTab、uni.navigateBack// 并且对相应的方法做重写const original = uni[type];uni[type] = function (options = {}) {const { url: path } = options;if (!whiteList.includes(path) && !uni.getStorageSync("token")) {// 判断是否存在token,不存在重定向到登录页uni.$e.route("/pages/login/index");} else {return original.call(this, options);}};});};const install = function (Vue, options) {uni.$e = { route };Vue.prototype.route = route;// 重写uni方法handleOverwirteRoute();// 路由拦截器uni.$e.routeIntercept = (routeConfig, resolve) => {const path = routeConfig.url.split("?")[0];if (!whiteList.includes(path) && !uni.getStorageSync("token")) {uni.$e.route("/pages/login/index");return;}resolve(true);};};export default {install,}; 补充

在系统第一进入的时候,是不会触发拦截事件的,需要在App.js的onLanch去做进一步的实现。

onLaunch: function () {if (!uni.getStorageSync("token")) {uni.navigateTo({ url: "/pages/login/index" });}},

小结

关于uni-app实现路由拦截的探索到这里就告一段落了,三种方式都是可以的,uni-simple-router使用人数也挺多的,不考虑跨很多端,暴露出来的问题可能就比较少,也是一种选择。第二种方式,重写uni的跳转方式,比较简单,效果也是很明显,不过使用稍微没那么友好,需要做进一步封装,第三种方式算是做了封装,同时结合第二种方式,算是有个比较好的效果。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。 有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文链接地址:https://www.jiuchutong.com/zhishi/288810.html 转载请保留说明!

上一篇:pytorch :OSError: [WinError 1455] 页面文件太小,无法完成操作。 Error loading 【已解决】

下一篇:最华丽的大中华区苹果商店(美丽的大中华)

  • 支付宝车辆停驶怎么没有没有能量了(支付宝车辆停驶一周几次)

    支付宝车辆停驶怎么没有没有能量了(支付宝车辆停驶一周几次)

  • 腾讯会员怎么使用手机号登录(腾讯会员怎么使用手机号码登录)

    腾讯会员怎么使用手机号登录(腾讯会员怎么使用手机号码登录)

  • 戴尔win10睡眠无法唤醒(戴尔电脑进入休眠唤醒不了)

    戴尔win10睡眠无法唤醒(戴尔电脑进入休眠唤醒不了)

  • internet是什么结构的网络(internet结构)

    internet是什么结构的网络(internet结构)

  • 拼多多买家不确认收货后多久到账(拼多多买家不确定收货钱是不是不会到卖家那里去?)

    拼多多买家不确认收货后多久到账(拼多多买家不确定收货钱是不是不会到卖家那里去?)

  • 注销手机号后绑定的东西怎么办(注销手机号后绑定的支付宝怎么办)

    注销手机号后绑定的东西怎么办(注销手机号后绑定的支付宝怎么办)

  • iqoo有系统分身吗(iqoo5系统分身)

    iqoo有系统分身吗(iqoo5系统分身)

  • 小米10变焦多少倍(小米10变焦能力)

    小米10变焦多少倍(小米10变焦能力)

  • 苹果手机镜面翻转在哪里(苹果手机镜面翻转怎么关)

    苹果手机镜面翻转在哪里(苹果手机镜面翻转怎么关)

  • 删除拉黑后显示什么(拉黑和删除微信显示)

    删除拉黑后显示什么(拉黑和删除微信显示)

  • 钉钉清空聊天记录后还能恢复吗(钉钉清空聊天记录在另一台设备登陆还有记录吗)

    钉钉清空聊天记录后还能恢复吗(钉钉清空聊天记录在另一台设备登陆还有记录吗)

  • 9400f配什么主板(9400f配什么主板能用3200内存条)

    9400f配什么主板(9400f配什么主板能用3200内存条)

  • 水星路由器恢复出厂设置后连不上网怎么办(水星路由器恢复出厂设置)

    水星路由器恢复出厂设置后连不上网怎么办(水星路由器恢复出厂设置)

  • 苹果11qq消息来,为什么没有提示(苹果11qq收到消息没有提示音)

    苹果11qq消息来,为什么没有提示(苹果11qq收到消息没有提示音)

  • 抖音绿色是关闭还是打开(抖音绿色是关闭还是打开视频)

    抖音绿色是关闭还是打开(抖音绿色是关闭还是打开视频)

  • 全民k歌可以两个人同时唱一首歌吗(全民K歌可以两个地方登录吗)

    全民k歌可以两个人同时唱一首歌吗(全民K歌可以两个地方登录吗)

  • 华为辅助键怎么开启(华为辅助键怎么关掉)

    华为辅助键怎么开启(华为辅助键怎么关掉)

  • 快手推广审核中是什么情况(快手推广审核未通过会退款吗)

    快手推广审核中是什么情况(快手推广审核未通过会退款吗)

  • 华为m6平板能接u盘吗(华为m6平板可以type c转hdmi)

    华为m6平板能接u盘吗(华为m6平板可以type c转hdmi)

  • 耳机外放是什么情况(耳机外放声音大是好还是坏)

    耳机外放是什么情况(耳机外放声音大是好还是坏)

  • 8p是什么处理器(苹果14plus是什么处理器)

    8p是什么处理器(苹果14plus是什么处理器)

  • 华为屏保图片怎么关闭(华为屏保图片怎么截图)

    华为屏保图片怎么关闭(华为屏保图片怎么截图)

  • 微信不是好友能举报投诉吗(微信不是好友能拍一拍吗)

    微信不是好友能举报投诉吗(微信不是好友能拍一拍吗)

  • 学习通如何退出班级

    学习通如何退出班级

  • opporeno有无线充电吗(oppo手机reno无线充电器怎么用)

    opporeno有无线充电吗(oppo手机reno无线充电器怎么用)

  • 微博发图怎么不带水印(微博发图怎么不变成live)

    微博发图怎么不带水印(微博发图怎么不变成live)

  • 如何更新PC端微信版本?(pc端微信怎么更新)

    如何更新PC端微信版本?(pc端微信怎么更新)

  • java图片转二进制流_java将文件转化成二进制流(java图片转换成文件流)

    java图片转二进制流_java将文件转化成二进制流(java图片转换成文件流)

  • Tomcat服务器部署+Web项目搭建(tomcat服务器在哪个位置)

    Tomcat服务器部署+Web项目搭建(tomcat服务器在哪个位置)

  • 有限合伙需要报增值税吗
  • 销售收入怎么计算销项税额
  • 企业所得税的计提
  • 加计抵扣进项税额政策2022
  • 发票货物名称前带星号规定
  • 维修费开票属于哪个大类
  • 企业所得税季度预缴怎么计算
  • 个体户核定5万每个月要交多少税钱
  • 收到虚开的普票已经入账怎么调账
  • 无形资产和固定资产的折旧
  • 新准则前期差错更正
  • 公司车子的保养费怎么算
  • 积分兑换礼品需要缴纳个人所得税吗
  • 物业公司销售门禁卡属于什么收入
  • 借用另一家公司名义
  • 售后回租的实际操作流程
  • 经营期间银行存在的问题
  • 收取线路维护费合法吗
  • 会务费税前扣除比例
  • 小规模纳税人可以享受小微企业吗
  • 定率征收怎么申报
  • 个人财产税是什么意思
  • 出纳人员发现假章怎么办
  • 固定资产清理出售合同
  • 金税盘减免税款怎么结转
  • php二维数组添加数据
  • 网络连接错误是什么意思啊
  • 投资性房地产转换日公允价值大于账面价值
  • 无偿受赠房产出售税费
  • DWHeartbeatMonitor.exe进程是什么意思 DWHeartbeatMonitor是安全的进程吗
  • 购进免税农产品进行进项税额抵扣时,其抵扣率为
  • 发财树怎么修剪枝叶视频教程
  • bug的5个级别
  • php读取mysql
  • vscode安装python3
  • transformer中的参数
  • webpack devserver contentbase
  • 外贸公司美金账户维护费用
  • 出口海运费222011
  • 苹果2021年在中国不能用了吗
  • 人工费按照考虑管理费和利润吗
  • 农产品进项税抵扣填报方法
  • 什么是企业所得税收入
  • 合并范围外关联方需要函证吗
  • mongodb findandmodify
  • 企业购进生产设备的会计分录
  • PostgreSQL教程(十五):系统表详解
  • 设计部工资计入哪个科目
  • 信用减值损失转回的会计处理
  • 交易性金融资产属于流动资产
  • 规模以上企业纳税要求
  • 研发过程4个主要阶段
  • 不良品扣款会计分录
  • 招待费进项税额可以抵扣吗
  • 公司租用房屋用交房产税吗
  • 税负率偏低
  • 结余资金结转申请怎么写
  • 本期应征增值税销售额是什么意思
  • 根据银行回单做凭证
  • 药品进销差价科目明细
  • sql 复合语句
  • sql查询字段值为汉字的
  • mysql字符串类型有哪些
  • arch linux安装yay
  • 升级ubuntu
  • 如何禁止mac adobe acrobat联网
  • linux中python命令
  • 笔记本如何一键锁屏快捷键
  • winole.exe - winole是什么进程
  • javascript基础教程教材答案
  • bash脚本语法
  • node.js在网页制作中的作用
  • linux怎么使用
  • 基于unity3d
  • 个体户开票怎么开步骤
  • 辽宁省国家税务总局
  • 天府新区劳动局投诉电话
  • 国税 地税比例
  • 湖北省国家税务局官网
  • 办税服务厅是税收工作的
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设