javascript - 如何在Angular/Angular 9中初始化之前动态创建路由

标签 javascript angular typescript angular-router angular9

我正在开发一个将 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 应用的基本工作流程:
  • AngularJS 应用程序不会立即使用绑定(bind)到元素
    ng-app,就像通常完成的那样。
  • 在页面加载时从 API 接收原始(或 jQuery)响应。
  • AngularJS 应用程序使用以下命令初始化:

  •  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/

    相关文章:

    node.js - Angular + Electron 应用程序 : query web API or DataBase according to deskop or web mode

    typescript - mat-tab-nav-bar 标签没有显示

    javascript - Angular 2 : array. splice() 正在从 DOM 中删除元素

    node.js - 如何在 Typescript 中启用 NodeJS 和 ExpressJs

    javascript - Highcharts xAxis 类别未正确显示

    java - jquery ajax返回未找到的元素

    javascript - jquery-ui 对话框显示无内容(请参阅更新 3)

    javascript - 如何用 JSCS 规则替换弃用的 JSHint 选项?

    angular - 将类应用于 Angular 中的每个路由组件

    javascript - 使用 AngularJS 2 和 ES6 的 HTTP GET 请求