基于mpvue-router-patch实现路由拦截

目录

本文目的在于记录mpvue-router-patch-interceptor的实现过程,基于mpvue-router-patch,以及我以前的两篇博客:JavaScript异步函数同步方法 和 基于koa2中间件原理实现拦截任意对象方法的调用,实现mpvue的页面路由跳转拦截器,这个我已经发布到npm上去了,就叫做mpvue-router-patch-interceptor,由于我自己在测试的时候,发现如果使用mpvue-entry这个插件,我这个就用不了了,提示在mpvue-entry生成的js文件中找不到mpvue-router-patch-interceptor,具体原因我还在找,不过同学们可以直接从这里讲源码拿去用,代码不多。

源码
/*
*   creator:      weishengjian
*   time:         2018.7.15  16:41
*/

import MpvueRouterPatch from 'mpvue-router-patch'
import {pushArray} from "./utils";

let $router;                                  //mpvue-router-patch插件注册的$router对象
let $push;                                    //mpvue-router-patch插件注册的$router.push方法
let everyMiddlewares = [];                    //全局中间件,拦截所有路由跳转
let matchMiddlewares = {};                    //路由地址匹配中间件,key为匹配路径的正则表达式字符串、value为中间件数组

/*
* 页面跳转中间件,执行页面跳转动作
*/
async function pushMiddware(...args) {
    // console.log('into original push middlewares')
    $push(...args);
}

/*
* 合并异步中间件方法
*/
function compose(middlewares) {               //异步中间件同步方法
    return function (...args) {
        function dispatch(i) {
            let fn = middlewares[i];
            if (!fn) {
                return Promise.resolve();
            }
            else {
                return Promise.resolve(fn(
                    ...args,
                    function next() {
                        return dispatch(i + 1)
                    }
                ))
            }
        }

        return dispatch(0);
    }
}

function getMatchMiddlewares(path) {
    let ret = [];
    for (let regexp in matchMiddlewares) {
        // console.log(regexp, path, new RegExp(regexp).test(path))
        if (new RegExp(regexp).test(path))
            pushArray(ret, matchMiddlewares[regexp])
    }
    return ret;
}

let MpvueRouterPatchInterceptor = {
    install(Vue, {every, match}) {
        Vue.use(MpvueRouterPatch);
        console.log('Vue.prototype.$router', Vue.prototype.$router)
        $router = Vue.prototype.$router
        $push = $router.push
        pushArray(everyMiddlewares, every)
        matchMiddlewares = Object.assign({}, match)

        /*重写mpvue-router-patch的$router.push方法*/
        $router.push = async (...args) => {
            // console.log('push start-->>', args)
            let option = typeof args[0] === 'string' ? {path: args[0]} : args[0]
            let fn = compose(everyMiddlewares.concat(getMatchMiddlewares(option.path)).concat([pushMiddware]));
            fn(option);
            // console.log('push end')
        }
    },
    every(everyMiddleware) {
        everyMiddlewares.push(everyMiddleware)
    },
    match(regexp, middleware) {
        (!matchMiddlewares[regexp]) && (matchMiddlewares[regexp] = [])
        matchMiddlewares[regexp].push(middleware)
    },
    sayHello() {
        console.log('hello')
    },
}

export default MpvueRouterPatchInterceptor
utils文件代码
export function pushArray(targetArray, dataArray) {
    if (!dataArray) return
    if (!dataArray instanceof Array) {
        console.error('dataArray的参数必须是一个数组');
        return;
    }
    dataArray.forEach((item) => {
        targetArray.push(item);
    })
}

用法:

在mpvue工程src/main.js中

import MpvueRouterPatchInterceptor from "./common/mpvue-router-patch-interceptor";
import {every, match} from "./common/router-interceptors";
Vue.use(MpvueRouterPatchInterceptor, {every, match});

其中every和match是自定义的拦截器,every为拦截所有路由,match为拦截正则表达式匹配的路由,every为数组,match为对象,实例代码:

/*
*   power by    weishengjian
*   datetime    2018/7/14 10:32
*   desc:       页面跳转路由拦截器
*/

import {hideLoading, showLoading, showModal} from "./msg";
import {delay} from "./mpvue-router-patch-interceptor";

export let every = [
  async (option, next) => {
    console.log('1 start')
    showLoading()
    await delay(100)
    await next();
    hideLoading()
    console.log('1 end')
  },
  async (option, next) => {
    console.log('2 start')
    await delay(200)
    await next()
    console.log('2 end')
  },
  async (option, next) => {
    console.log('3 start')
    await delay(300)
    await next()
    console.log('3 end')
  }
]

export let match = {
  '/pages': [
    async (option, next) => {
      console.log('match /pages', option)
      next()
    }
  ],
  '/pages/dev': [
    async (option, next) => {
      console.log('match /pages/dev', option)
      if (option.query.name !== '111') {
        showModal('name 不为111');
      } else {
        next()
      }
    }
  ]
}

你可能感兴趣的:(前端)