uniapp或者微信小程序如何封装一个类似于vue-router中的beforeEach功能?

582 阅读1分钟

uniapp中的路由跳转有5种方法:uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab,uni.navigateBack,工作中有时候会遇到一些特殊需求,需要在页面跳转前做一些逻辑处理,此时,我们可以使用Reflect.defineProperty对uniapp中的这5个方法就行劫持来实现我们的业务场景,我们创建一个route.js文件

class Router {
	routerBeforeCallBack = null
	list = ['navigateTo', 'navigateBack', 'redirectTo', 'reLaunch', 'switchTab']
	constructor() {
		this.init()
	}
	init() {
		let _this = this
		let originRouterTypes = {
			navigateTo: uni.navigateTo,
			navigateBack: uni.navigateBack,
			redirectTo: uni.redirectTo,
			reLaunch: uni.reLaunch,
			switchTab: uni.switchTab
		}
		_this.list.forEach((item) => {
			Reflect.defineProperty(uni, item, {
				configurable: true,
				enumerable: true,
				writable: true,
				value: (arg) => {
					try {
						let pages = getCurrentPages()
						let fromPage = {
							path: `/${pages[pages.length - 1].route}`,
							query: pages[pages.length - 1].options
						}
						let toPage = {}
						if (item === 'navigateBack') {
							let n = arg.delta ? arg.delta : 1
							toPage = {
								path: pages[pages.length - 1 - n].route,
								query: pages[pages.length - 1 - n].options
							}
						} else {
							toPage = _this._formateUrl(arg)
						}

						_this.routerBeforeCallBack(toPage, fromPage, (params) => {
							if (params === undefined || params === true) {
								return originRouterTypes[item].call(null, arg)
							} else if (params === false) {
								return false
							} else if (Object.prototype.toString.call(params) === '[object Object]') {
								return originRouterTypes[item].call(null, params)
							}
						})
					} catch (error) {
						return originRouterTypes[item].call(null, arg)
					}
				}
			})
		})
	}

	beforeEach(callback) {
		if (Object.prototype.toString.call(callback) === '[object Function]') {
			this.routerBeforeCallBack = callback
		} else {
			throw new Error('argument must be a function')
		}
	}

	_formateUrl(param) {
		let path = ''
		let queryStr = ''
		let json = {}
		path = param.url.split('?')[0]
		queryStr = param.url.split('?')[1]
		if (queryStr) {
			json = parseSearchParams(queryStr)
		}
		return {
			path,
			query: json
		}
	}
}
export default new Router()
function parseSearchParams(search) {
	const pairs = search ? search.split('&') : []
	const query = {}
	for (let i = 0; i < pairs.length; ++i) {
		const [key, value] = pairs[i].split('=')
		query[key] = query[key] || decodeURIComponent(value)
	}
	return query
}

然后,我们在main.js里面引入这个文件

import router from './src/common/router.js'
router.beforeEach((to, from, next) => {
    // 这里去写一些路由跳转逻辑
})