基于 Vue-Router 语言的路由前缀

Jes*_*tes 5 vue.js vue-router vuejs2 vue-i18n

我使用它prerender-spa-plugin是为了预渲染某些页面,以便从我的 Vue 应用程序中获得更好的 SEO。

我的目标是改变我目前使用的方式Vue-i18n,所以我可以基于 url param /lang。示例:/en/home/nl/home。有了这个,我将能够根据语言进行预渲染。

我创建了一个前缀函数,该函数将可选的 param 添加到每个父路由/:lang?。这里是:

const withPrefix = (prefix: string, routes: RouteConfig[]): RouteConfig[] => routes.map((route): RouteConfig => {
  // Avoiding mutations
  const clonedRoute = { ...route };
  // Every route except for '/'
  if (clonedRoute.path !== '/') {
    clonedRoute.path = prefix + clonedRoute.path;
  }
  return clonedRoute;
});
Run Code Online (Sandbox Code Playgroud)

在 Vue 模板中,我使用:

<router-link :to="`/account`">
Run Code Online (Sandbox Code Playgroud)

所以我试图根据参数操纵重定向下一页lang

第一种方法

最合乎逻辑的一个是(在 Router 的内部beforeEach):

const { lang } = to.params;
const redirectTo = lang ? to.fullPath : `${fullToLang}${to.fullPath}`;
if (from.fullPath !== redirectTo) {
  next({ path: redirectTo });
} else {
  next();
}
Run Code Online (Sandbox Code Playgroud)

但它进入无限循环,因为 from 总是相同的。

第二种方法

使用Routerbase属性。

import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld";
import Test from "./components/Test";

Vue.config.productionTip = false;

Vue.use(VueRouter);

const router = new VueRouter({
  mode: "history",
  base: "/en",
  routes: [
    {
      path: ":lang?/",
      component: HelloWorld,
      beforeEnter: (to, from, next) => {
        console.log(1);
        next();
      }
    },
    {
      path: "/:lang?/nope",
      component: Test,
      beforeEnter: (to, from, next) => {
        console.log(2);
        next();
      }
    },
    {
      path: "/:lang?/*",
      beforeEnter: (to, from, next) => {
        console.log(to);
        next("/nope");
      }
    }
  ]
});

new Vue({
  render: h => h(App),
  router
}).$mount("#app");
Run Code Online (Sandbox Code Playgroud)

或者更好,直播:https : //codesandbox.io/embed/vue-template-0bwr9

但是,我不明白为什么它仅在路由上找不到 url 时才重定向/en/nope(最后一种情况)。更重要的是,Router每次我想更改时base是否都必须创建一个新实例?

第三种方法

包装部件用于router-link注入:to根据this.$route.params.lang

这将在应用程序加载后但不是在第一次刷新/初始化时进行导航。

那么,我应该如何解决这个问题?

~解决方案~

所以是的,第一种方法是正确的方法,但我误解了 Router 与next和 的行为方式redirects。条件应该是检查to不是from

const redirectTo = lang ? to.fullPath : `${fullToLang}${to.fullPath}`;
if (to.fullPath !== redirectTo) {
  // Change language at i18n
  loadLanguageAsync(toLang as Language);

  next({ path: redirectTo });

  return;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*cRo 2

我不完全确定你在问什么。但我假设您想在导航中添加当前语言参数 (../en/..) 的前缀(如果导航还没有)?

您可以使用钩子来解决此问题beforeEach(),并且仅在不存在lang参数时才进行重定向。

const { lang } = to.params
if(!lang) {
  next({ path: redirectTo })
}
next()
Run Code Online (Sandbox Code Playgroud)

如果这不是您想要的,请澄清,我会编辑我的答案