uniapp+vue3+ts基于uview的路由跳转进行修改
route.ts/*** 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷* 并且带有路由拦截功能*/import { deepClone, page, deepMerge } from '@/utils'type ToPageType =| 'navigateTo'| 'to'| 'redirectTo'| 'redirect'| 'switchTab'| 'tab'|
·
route.ts
/**
* 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
* 并且带有路由拦截功能
*/
import { deepClone, page, deepMerge } from '@/utils'
type ToPageType =
| 'navigateTo'
| 'to'
| 'redirectTo'
| 'redirect'
| 'switchTab'
| 'tab'
| 'reLaunch'
| 'launch'
| 'navigateBack'
| 'back'
interface conFig {
type: ToPageType,
url: string,
delta: number,
params: initBody,
animationType: string,
animationDuration: number,
intercept: boolean,
routeIntercept: Function
}
interface routerObj {
url: string,
type?: ToPageType,
params?: initBody,
delta?: number
}
class Router {
public config: conFig
constructor() {
// 原始属性定义
this.config = {
type: 'navigateTo',
url: '',
delta: 1, // navigateBack页面后退时,回退的层数
params: {}, // 传递的参数
animationType: 'pop-in', // 窗口动画,只在APP有效
animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
intercept: false, // 是否需要拦截
routeIntercept: (mergeConfig: any, resolve: any) => {
// 处理或判断参数
resolve(true)
} // 拦截器
}
// 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
// 这里在构造函数中进行this绑定
this.route = this.route.bind(this)
}
// 判断url前面是否有"/",如果没有则加上,否则无法跳转
addRootPath(url: string) {
return url[0] === '/' ? url : `/${url}`
}
// 整合路由参数
mixinParam(url: string, params: initBody = {}) {
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
if(Object.prototype.toString.call(params).slice(8, -1) === 'Object') {
query = encodeURIComponent(JSON.stringify(params))
if (/.*\/.*\?.*=.*/.test(url)) {
// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
return url += Object.keys(params).length > 0 ? `¶ms=${ query }` : ''
}
// 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
return url += Object.keys(params).length > 0 ? `?params=${ query }` : ''
} else {
throw Error('params type must be object')
}
}
// 对外的方法名称
async route(options: string | routerObj, params: any = {}) {
// 合并用户的配置和内部的默认配置
let mergeConfig: any = {}
if (typeof options === 'string') {
// 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
if (options === page()) return
// 如果options为字符串,则为route(url, params)的形式
mergeConfig.url = this.mixinParam(options, params)
mergeConfig.type = 'navigateTo'
} else {
mergeConfig = deepClone(options)
// 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
if (mergeConfig.url === page()) return console.log('鱼鱼路由跳转提示:请不要重复点击~~~')
// 否则正常使用mergeConfig中的url和params进行拼接
mergeConfig.url = this.mixinParam(options.url, options.params)
}
if (params.intercept) {
this.config.intercept = params.intercept
}
// 合并内外部参数
mergeConfig = deepMerge(this.config, mergeConfig)
// 判断用户是否定义了拦截器
if (this.config.intercept && typeof this.config.routeIntercept === 'function') {
// 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
const isNext = await new Promise((resolve, reject) => {
this.config.routeIntercept(mergeConfig, resolve)
})
// 如果isNext为true,则执行路由跳转
isNext && this.openPage(mergeConfig)
} else {
this.openPage(mergeConfig)
}
}
// 执行路由跳转
openPage(config: any) {
// 解构参数
const {
url,
type,
delta,
animationType,
animationDuration
} = config
if (type == 'navigateTo' || type == 'to') {
uni.navigateTo({
url,
animationType,
animationDuration
})
}
if (type == 'redirectTo' || type == 'redirect') {
uni.redirectTo({
url
})
}
if (type == 'switchTab' || type == 'tab') {
uni.switchTab({
url
})
}
if (type == 'reLaunch' || type == 'launch') {
uni.reLaunch({
url
})
}
if (type == 'navigateBack' || type == 'back') {
uni.navigateBack({
delta
})
}
}
// 修改默认配置
setConfig(func: Fn) {
this.config = func(this.config)
}
}
const _router = new Router()
// _router.setConfig((config: any)=> {
// config.intercept = true // 开启路由拦截
// config.routeIntercept = (params: any, resolve: any) => {
// resolve(false)
// }
// return config
// })
export default _router.route
/**
* @description 深度克隆
* @param {object} obj 需要深度克隆的对象
* @returns {*} 克隆后的对象或者原值(不是对象)
*/
export function deepClone(obj: any) {
// 对常见的“非”值,直接返回原来值
if ([null, undefined, NaN, false].includes(obj)) return obj
if (typeof obj !== 'object' && typeof obj !== 'function') {
// 原始类型直接返回
return obj
}
const o: any = test.array(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 function deepMerge(target: any = {}, source: any = {}) {
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 function page() {
const pages = getCurrentPages()
// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
return `/${pages[pages.length - 1]?.route ?? ''}`
}
/**
* @description 页面跳转获取参数
* @returns Object
*/
export function transQuery(params: string | undefined): initBody{
if(params) {
return JSON.parse(decodeURIComponent(params))
} else {
return {}
}
}
使用方法
const toPage = () => {
// _route('/pages/index/xiaoai')
_route({
url: '/pages/index/xiaoai'
})
}
解析数据
onLoad((options)=>{
const query = transQuery(options.query)
userName.value = query.name
age.value = query.age
})
更多推荐
已为社区贡献4条内容
所有评论(0)