【问题标题】:load routes via component from external api and add them to the router通过组件从外部 api 加载路由并将它们添加到路由器
【发布时间】:2019-10-20 18:57:21
【问题描述】:

我想从外部 API 加载我的路线。某些用户可能没有访问模块的权限。

所以我的导航栏会调用 API 并获取所有返回的模块。这些模块对象包含视图文件的路径。

我尝试创建一个小沙盒来重现问题

https://codesandbox.io/s/vue-routing-example-i5z1h

如果您在浏览器中打开此网址

https://i5z1h.codesandbox.io/#/First

你会首先得到以下错误

网址/第一个未找到

但点击导航栏中的第一个模块链接后,应该会呈现第一个视图。

我认为问题与页面加载后尚未启动导航创建事件有关,因此未找到模块页面。更改路由器 URL 后,导航组件有足够的时间将所有需要的路由添加到路由器。

如何在路由器引导至第一条路由并响应 404 错误之前加载这些 URL?

【问题讨论】:

  • 这个问题的第一个答案可能对你有帮助:stackoverflow.com/questions/46341016/… 解决方案基本上是在路由加载后初始化Vue实例
  • 谢谢西蒙,但我认为给定的示例使用与我没有相同的代码?我也使用this.$router.addRoutes。你介意为Solution is basically to initialize the Vue instance after the routes have been loaded提供一个例子吗?
  • @hrp8sfH4xQ4 你的路由器设置很不寻常。路由在Navbar.vue 中延迟添加。你为什么在router.js中设置路由而不是在router.js
  • @hrp8sfH4xQ4 在router.js 中设置路由时请参阅difference in behavior

标签: vue.js vue-router


【解决方案1】:

这里的关键思想是异步加载路由,这意味着您必须将 SPA 的加载推迟到那个时候。在您的index.jsmain.js 中,您的代码将是这样的:

// Some functions are assumed and not defined in the below code.
import Vue from 'vue';
import VueRouter from 'vue-router';

// Application root component
import App from './App.vue';
import { getRoutes } from './api';

// Register Vue plugins
Vue.use(VueRouter);


// Make API call here

// Some animation before the app is fully rendered.
showLoader();

getRoutes(/* Optional User data */)
  .then((routesData) => {
    // Stop the animation
    stopLoader();
    return routesData;
  })
  .then((routesData) => {

    // processRoutes returns an array of `RouteConfig`
    const routes = processRoutes(routesData);

    const router = new Router({
      routes: [
        ...routes,
        {
          path: '*',
          component: NotFound
        }
      ]
    });
  })
  .then((router) => {
    const app = new Vue({
      el: '#app',
      router,
      template: '<App/>',
      components: { App }
    });
  });

此外,您还需要做一些事情:

  • 路由通常是更高级别的关注点。因此,如果您考虑DIP - Dependency Inversion 和路由器的有状态+单例性质,那么在一开始就引导它是有意义的。因此,路由器需要的任何东西都应该可用。这意味着navbar 组件不应该负责进行 API 调用。你必须把它拿出来。
  • 另一种可能的解决方案是使用$router.addRoutes() 方法。但这不足以满足您的需求。考虑到授权是行不通的。它不会妨碍导航。
  • 在哲学层面上,当您使用带有客户端路由的 SPA 时,客户端路由就是它自己的事实来源。预先知道所有路由是合理的,因此大多数路由器在设计时都考虑到了这个想法。因此,像这样的要求不适合这种范式。如果您需要这样的东西,那么服务器应该拥有客户端路由的知识,并且在页面刷新期间,服务器应该决定做什么 - 加载 SPA 或拒绝 404/403 页面。如果允许访问,服务器应该在 HTML 页面中注入路由数据,然后由浏览器端的 Vue.js 选择。存在许多复杂的 SSR - 服务器端渲染技术来实现这一点。

替代策略:使用警卫

  1. 为所有用户的所有可能视图预先定义路由器中的所有路由。
  2. 为每条授权路线定义守卫。所有这些守卫都将被异步解决。
  3. 不是从 API 加载路由数据,而是使用 API 返回一个授权矩阵。在您的路由保护中使用此 API 响应来确定访问权限。
  4. 为防止多次调用同一个 API,您可以使用某种缓存,例如 Proxy、Memoization、store 等。通常,对于用户而言,Auth Matrix 在调用之间不会发生变化.

这样做的一个优势是,如果需要,您仍然可以部分加载应用程序,从而通过减少用户与应用程序交互的时间来获得有意义的用户体验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多