我想从外部 API 加载我的路线。某些用户可能没有访问模块的权限。
所以我的导航栏进行 API 调用并获取返回的所有模块。这些模块对象包含 View 文件的路径。
我尝试创建一个小沙箱来重现该问题
https://codesandbox.io/s/vue-routing-example-i5z1h
如果您在浏览器中打开此网址
https://i5z1h.codesandbox.io/#/First
首先会报如下错误
Url /First not found
但是在点击导航栏中的第一个模块链接后,应该会呈现第一个 View 。
我认为问题与页面加载后还没有启动导航创建事件有关,因此找不到模块页面。更改路由器 URL 后,导航组件有足够的时间将所有必需的路由添加到路由器。
如何在路由器引导到第一个路由并响应 404 错误之前加载这些 URL?
最佳答案
这里的关键思想是异步加载路由,这意味着您必须将 SPA 的加载推迟到那个时候。在您的 index.js
或 main.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 页面中注入(inject)路由数据,然后由浏览器端的 Vue.js 选择。许多复杂的SSR - 服务器端渲染技术都可以实现这一点。
替代策略:使用守卫
- 在路由器中为所有用户的所有可能 View 预先定义所有路由。
- 为每条授权路线定义守卫。所有这些守卫都将异步解决。
- 不是从 API 加载路由数据,而是使用 API 返回一个授权矩阵。在您的路由守卫中使用此 API 响应来确定访问权限。
- 要防止多次调用同一 API,您可以使用某种缓存,例如代理、内存、存储等。通常,对于用户而言,Auth Matrix 不会因调用而异.
这样做的一个优势是,如果需要,您仍然可以部分加载应用程序,从而减少用户与应用程序交互的时间,从而带来有意义的用户体验。
关于vue.js - 通过组件从外部 api 加载路由并将它们添加到路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56457536/