简洁的路由
之前也写过一篇关于路由的封装,但是没有拦截器
uni-app 插件市场也有很多封装好的路由,也有几个非常好的,自己为什么不用了,因为封装过渡了(代码的大小几十kb到一百多kb,要是可以插件化,选择自己的功能就完美了),要知道小程序是有限制包大小的,就算没有,我们也应该尽量小,而且有很多功能我是使用不到的
现在简化以前的路由,下面的代码只是在自己的项目下使用没有什么问题,大家参考修改适合自己的项目就可以了
// 这是基本结构
// 把 uni 路由 promise 化
class Router {
push ({ type = 'navigateTo', url }) {
const promise = new Promise((resolve, reject) => {
uni[type]({
url: url,
success: resolve,
fail: reject
})
})
return promise
}
back (delta = 1) {
uni.navigateBack({ delta })
}
}
怎么处理带参数的路由
// 先看看使用方式
const router = new Router()
router.push({
path: '/pages/index/index',
query: { id: 1 }
})
// 获取拼接好的 url
const getUrl = (path, query) => {
let url = path
if (Object.prototype.toString.call(query) === '[object Object]') {
url = `${path}?query=${JSON.stringify(query)}`
}
return url
}
添加拦截器
只提供全局的 beforeEach 和 afterEach 拦截器
// 先看使用方式
const router = new Router()
router.beforeEach((to, from, next) => {
console.log('beforeEach', to, from)
if (to.path === '/pages/test/index') {
next({
path: '/pages/login/index'
})
return
}
next()
})
router.afterEach((to, from) => {
console.log('afterEach', to, from)
})
// to form 参数包含两个参数 path: 跳转的路径 query: 路由所带参数
// 下面创建一个获取 to form 的方法
const getToAndFrom = ({ path, query }) => {
let from = {}
// getCurrentPages 这个是原生函数用于获取当前页面栈的实例
const routers = getCurrentPages()
if (routers.length > 0) {
// 获取最后一个元素
const router = routers[routers.length - 1]
// 这下面的逻辑结合上面的 getUrl 方法
const { query, ...options } = router.options
let args = options
if (query) {
args = {
...args,
...JSON.parse(query)
}
}
from = {
path: router.route,
query: args
}
}
const to = {
path,
query: query || {}
}
return {
to,
from
}
}
// 创建一个 next 方法
// 用于 beforeEach 拦截
_next ({ to, from }) {
let i = 0
return new Promise((resolve, reject) => {
const _next = (args) => {
if (Object.prototype.toString.call(args) === '[object Object]') {
this.push(args)
return reject('拦截并跳转')
}
if (args === false) {
return reject('拦截终止跳转')
}
const task = this._beforeEach[i++]
if (!task) {
return resolve()
}
// 重要的是这里
return new Promise((next) => {
task(to, from, next)
}).then(_next).catch(reject)
}
_next()
})
}
push (params) {
const { type, path, query } = params
// getToAndFromAndUrl 这个方法是合并上面的 getToAndFrom 和 getUrl 方法
const { to, from, url } = getToAndFromAndUrl({ path, query })
// 这里调用 beforeEach 拦截器
return this._next({ to, from }).then(() => {
// _push 就是上面的 push
return this._push({ type, url, to, from })
}).catch(err => {
console.log(err)
})
}
完整代码
// 获取拼接好的 url、to、from
const getToAndFromAndUrl = ({ path, query }) => {
let url = path
let from = {}
const routers = getCurrentPages()
if (routers.length > 0) {
const router = routers[routers.length - 1]
const { query, ...options } = router.options
let args = options
if (query) {
args = {
...args,
...JSON.parse(query)
}
}
from = {
path: router.route,
query: args
}
}
if (Object.prototype.toString.call(query) === '[object Object]') {
url = `${path}?query=${JSON.stringify(query)}`
}
const to = {
path,
query: query || {}
}
return {
to,
from,
url
}
}
export default class Router {
_beforeEach = []
_afterEach = []
_push ({ type = 'navigateTo', url, to, from }) {
const promise = new Promise((resolve, reject) => {
uni[type]({
url: url,
success: resolve,
fail: reject
})
})
promise.then(() => {
// 跳转成功后了调用 afterEach 拦截器
this._afterEach.forEach(fn => {
fn(to, from)
})
}).catch(err => {
console.log(err)
})
return promise
}
push (params) {
const { type, path, query } = params
const { to, from, url } = getToAndFromAndUrl({ path, query })
return this._next({ to, from }).then(() => {
return this._push({ type, url, to, from })
}).catch(err => {
console.log(err)
})
}
_next ({ to, from }) {
let i = 0
return new Promise((resolve, reject) => {
const _next = (args) => {
if (Object.prototype.toString.call(args) === '[object Object]') {
this.push(args)
return reject('拦截并跳转')
}
if (args === false) {
return reject('拦截终止跳转')
}
const task = this._beforeEach[i++]
if (!task) {
return resolve()
}
return new Promise((next) => {
task(to, from, next)
}).then(_next).catch(reject)
}
_next()
})
}
beforeEach (fn) {
this._beforeEach.push(fn)
}
afterEach (fn) {
this._afterEach.push(fn)
}
back (delta = 1) {
uni.navigateBack({ delta })
}
}
参数获取
function parseURL () {
const routers = getCurrentPages()
if (routers.length > 0) {
const router = routers[routers.length - 1]
const { query, ...options } = router.options
let args = options
if (query) {
args = {
...args,
...JSON.parse(query)
}
}
return args
}
return {}
}