我正在开发一个将 AngularJS 应用程序转换为 Angular 的项目,并且我正面临一个关于路由的阻止程序。
TL/DR:
在使用路由模块之前,我需要根据 API 响应定义路由。
AngularJS 中的工作场景:
(下面还有一些伪代码)
每个人都有几个基本路由,它们是在标准 AngularJS 方式中定义的:
/home
/settings
...etc
然后是基于 API 响应创建的动态路由
/purchase-requests
/invoices
/godzilla
...etc. Content doesn’t matter, basically, a dynamic list of routes that an existing API gives as an array of strings
现有 AngularJS 应用的基本工作流程:
ng-app,就像通常完成的那样。
angular.bootstrap(document.getElementById('mainElementId'),[‘appName']);
这是因为 AngularJS 的行为不是在加载时调用 .config() 而是在 Angular 应用程序的引导时调用,我们将其推迟到 API 响应之后。
今天工作的示例 AngularJS:
<script>
let appList = [];
const mainApp = angular.module('mainApp', ['ngRoute']);
// Controllers
mainApp.controller('mainController', mainController);
mainApp.controller('homeController', homeController);
mainApp.controller('appListController', appListController);
mainApp.controller('appSingleController', appSingleController);
mainApp.controller('errorController', errorController);
// config will not be called until the app is bootstrapped
mainApp.config(function($routeProvider) {
// Default routes that everyone gets
$routeProvider.when('/', { templateUrl: 'views/home.html', controller: 'homeController'});
$routeProvider.when('/home', { templateUrl: 'views/home.html', controller: 'homeController'});
// Add the dynamic routes that were retreived from the API
for (let appName in appList) {
$routeProvider.when(`/${appName}`, { templateUrl: 'views/app-list.html', controller: 'appListController'});
$routeProvider.when(`/${appName}/new`, { templateUrl: 'views/app-single.html', controller: 'appSingleController'});
$routeProvider.when(`/${appName}/view/:itemNumber`, { templateUrl: 'views/app-single.html', controller: 'appSingleController'});
}
$routeProvider.otherwise({ templateUrl: 'views/error.html', controller: 'errorController'});
});
$(document).ready(function() {
const options = {
type: 'GET',
url: '/api/apps/getAvailableApps',
success: onAppSuccess,
};
$.ajax(options);
});
function onAppSuccess(response) {
appList = response.appList;
angular.bootstrap(document.getElementById('mainApp'), ['mainApp']);
}
</script>
<!-- Typically, you bind to the app using ng-app="mainApp" -->
<div id="mainApp" class="hidden" ng-controller="mainController">
<!-- Route views -->
<div ng-view></div>
</div>
在 Angular 9(或者看似任何最新版本的 Angular)中,路由是在主组件初始化之前在路由模块中定义的:
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', component: DashboardComponent },
{ path: 'home', component: DashboardComponent },
{ path: 'settings', component: SettingsComponent },
];
使用
router.resetConfig
不工作假设我让主模块先加载 API 配置,然后使用
resetConfig
基于响应。如果用户加载的第一页是 /
,这将非常有用。或 /home
或其他预定义路线之一:创建新的动态路线并导航到它们。但是,如果用户直接导航到未预定义的路由(例如/godzilla),路由器甚至不允许页面加载(或)如果设置了通配符路由,则会显示 404。ngOnInit()在主要组件(我试图用来加载 API 响应)中永远没有机会运行。
问题是:如何在执行甚至初始化路由器导航之前根据 API 响应创建路由?
最佳答案
我添加动态路由的方式是使用参数预定义路由 url 模板。
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', component: DashboardComponent },
{ path: 'home', component: DashboardComponent },
{ path: 'settings', component: SettingsComponent },
{ path: ':appName', canActivate: AppGuard, children: [
{ path: '', component: AppListComponent },
{ path: 'new', component: 'NewAppComponent' },
{ path: 'view/:itemNumber', component: AppSingleComponent }
] },
{ path: '**', component: ErrorComponent }
];
路由是按顺序匹配的,所以“已知”的路由应该排在第一位。任何具有与“已知”路由不匹配的单个段的 URL 都将与
:appName
匹配。 .您可以声明一个守卫来验证 :appName
参数有效。如果不是,'**'
路线将被匹配。守卫看起来像这样:
@Injectable({ providedIn: 'root' })
export class AppGuard implements CanActivate {
constructor(private appService: AppService) {
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
const appName = route.params.appName;
return this.appService.isValidAppName(appName);
}
}
在哪里
appService.isValidAppName
是一些验证应用程序名称的函数。
关于javascript - 如何在Angular/Angular 9中初始化之前动态创建路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61693064/