美文网首页
router.push()和location.reload()搭

router.push()和location.reload()搭

作者: Bai_白 | 来源:发表于2023-07-25 16:51 被阅读0次

    项目背景

    一个后台管理系统,因为里面的内容由多个不同的项目组负责开发,于是领导要求将该系统重构成微前端。因该系统正在外部使用中,所以对微前端先进行用户试点,即登录使用的还是旧项目,在登录的时候识别该用户是否是微前端试点用户,是的话设置cookie的canary为‘always’,nginx会通过这个值去切换静态资源,而前端需要在登录成功后跳转到别的页面时使用location.reload()刷新去拿到最新的静态资源。


    nginx配置

    旧项目下登录后跳转的路由是/index/roomAudit。由于微前端划分了不同的子应用,菜单路由是后台配置的,所以路径先由前端写死了index替换,即微前端的路由会变成/operating/roomAudit(即这个路由对于旧项目来说是不存在的)。

    问题

    灰度方案(即使用canary去切换资源):会刷新login跳转后的页面(前提是项目跳不准确的路由不会报404)
    微前端:会跳回login页面刷新


    跳转后刷新

    原因

    使用灰度方案时,由于路由会由前端进行index替换成对应的子应用名字,所以router跳转的页面是不存在的;而单使用微前端时,路由名字已经是改成了对应的名字,对于项目来说router跳转的页面是存在的。那么问题可以转化为:

    1. router.push('不存在的页面A') -> location.reload()的页面效果为:跳转A,再刷新A页面
    2. router.push('存在的页面B') -> location.reload()的页面效果为:跳转B,再刷新login页面(原页面)
    function resolveAsyncComponents (matched) {
      return function (to, from, next) {
        var hasAsync = false;
        var pending = 0;
        var error = null;
    
        flatMapComponents(matched, function (def, _, match, key) {
          // if it's a function and doesn't have cid attached,
          // assume it's an async component resolve function.
          // we are not using Vue's default async resolving mechanism because
          // we want to halt the navigation until the incoming component has been
          // resolved.
          if (typeof def === 'function' && def.cid === undefined) {
            hasAsync = true;
            pending++;
    
            var resolve = once(function (resolvedDef) {
              if (isESModule(resolvedDef)) {
                resolvedDef = resolvedDef.default;
              }
              // save resolved on async factory in case it's used elsewhere
              def.resolved = typeof resolvedDef === 'function'
                ? resolvedDef
                : _Vue.extend(resolvedDef);
              match.components[key] = resolvedDef;
              pending--;
              if (pending <= 0) {
                next();
              }
            });
    
            var reject = once(function (reason) {
              var msg = "Failed to resolve async component " + key + ": " + reason;
              "development" !== 'production' && warn(false, msg);
              if (!error) {
                error = isError(reason)
                  ? reason
                  : new Error(msg);
                next(error);
              }
            });
    
            var res;
            try {
              res = def(resolve, reject);
            } catch (e) {
              reject(e);
            }
            if (res) {
              if (typeof res.then === 'function') {
                res.then(resolve, reject);
              } else {
                // new syntax in Vue 2.3
                var comp = res.component;
                if (comp && typeof comp.then === 'function') {
                  comp.then(resolve, reject);
                }
              }
            }
          }
        });
    
        if (!hasAsync) { next(); }
      }
    }
    

    通过查看vue-router源码发现,当要跳转的路由是不存在的情况下,hasAsync为false,直接next(),相当于是同步的,因此是先跳转路由再刷新页面,刷的就是跳转后的路由。当要跳转的路由是存在的情况下,会进入到resolve函数里,是异步的,就会先刷新而此时路由跳转过程还没有完成,就会导致刷新的是跳转前的页面。

    相关文章

      网友评论

          本文标题:router.push()和location.reload()搭

          本文链接:https://www.haomeiwen.com/subject/lsdhpdtx.html