uniapp跳转拦截

215 阅读1分钟

截止2024-2-1,网上找的插件有uni-simple-router和@gowiny/uni-router,前者vue2版本免费、vue3版本收费,后者是vue3但是打包报错 因为没找到合适的vue3用的路由插件,只能参照vue2的插件弄一个,只做了跳转的全局拦截,跟vue-router还是差很多的。

已知的问题有:

  1. 页面加载和跳转两种方式执行beforeEach和onload的顺序不同
  2. 监听或重写popstate和pushState等会报错,原因是编译到h5平台uniapp会自动引入vue-router,不允许进行popstate等的重写覆盖
  3. 小程序方面没试过,理论上也能用

最后,如果想要实现拦截,还是考虑付钱或者用回vue2。自己也是放弃这个用回vue2。

要是觉得有侵权请联系我

const isSameRoute = (a, b) => a === b && a !== "/" && b !== "/" && !!(a || b);

const navigateApis = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];

let initPageApis = [];
// 此处是因为百度小程序在onLoad之前会有onInit,但是这里只需要处理第一个执行的周期
// #ifdef MP-BAIDU
initPageApis = ["onInit"];
// #endif
// #ifndef MP-BAIDU
initPageApis = ["onLoad"];
// #endif
// 不用onReady是因为onReady执行一次但不是所有情况都执行,所以选择每次都执行的onShow
const showApis = ["onShow"];
const pageApis = [...initPageApis, ...showApis];

const navigateApisProxy = router => {
  navigateApis.forEach(key => {
    uni.addInterceptor(key, {
      invoke(config) {
        const { beforeEach, setTo, setFrom, setLockKey } = router;
        const pageArr = getCurrentPages();
        const currPath = pageArr[pageArr.length - 1]?.$page.fullPath;
        if (isSameRoute(config.url, currPath)) return false;

        if (beforeEach(config.url, currPath)) {
          setLockKey(key);
          setTo(config.url);
          setFrom(currPath);
          return true;
        }
        return false;
      },
      success() {
        const { afterEach, setFrom } = router;
        afterEach(router.to, router.from);
        setFrom(router.to);
      }
    });
  });
};
const pageApisMixin = router => ({
  // vue文件不要用这个生命周期
  beforeCreate() {
    // 只处理页面文件
    if (this.$mpType !== "page") return;
    pageApis.forEach(key => {
      const originFun = this.$[key] || [];
      Object.defineProperty(this.$, key, {
        get() {
          const { beforeEach, afterEach, setTo, setLockKey, setFrom } = router;
          const pageArr = getCurrentPages();
          const currPath = pageArr[pageArr.length - 1]?.$page.fullPath;

          initPageApis.includes(key) &&
            !navigateApis.includes(router.lockKey) &&
            setLockKey(key);

          showApis.includes(key) &&
            initPageApis.includes(router.lockKey) &&
            setLockKey("");

          if (!isSameRoute(currPath, router.from) && !router.lockKey) {
            if (beforeEach(currPath, router.from)) {
              return [
                () => {
                  afterEach(currPath, router.from);
                  setTo(currPath);
                  setFrom(currPath);
                },
                ...originFun
              ];
            }
            return null;
          }
          showApis.includes(key) && setLockKey("");
          return originFun;
        }
      });
    });
  }
});

export default {
  beforeEach: (to, from) => {
    console.log("before", to, from);
    // uni.navigateTo('/pages/login/login')
    return true;
  },
  afterEach: (to, from) => {
    console.log("after", to, from);
  },
  to: null,
  from: null,
  lockKey: "",
  setTo(to) {
    this.to = to;
  },
  setFrom(from) {
    this.from = from;
  },
  setLockKey(lockKey) {
    this.lockKey = lockKey;
  },
  install(app) {
    this.setFrom = this.setFrom.bind(this);
    this.setTo = this.setTo.bind(this);
    this.setLockKey = this.setLockKey.bind(this);
    navigateApisProxy(this);
    app.mixin(pageApisMixin(this));
  }
};