22

给定条件,我想将组件异步附加到路由。

以下示例有效(但是异步的),根据用户角色加载一个或另一个组件:

import { UserDashboardComponent }  from './user-dashboard.component'
import { AdminDashboardComponent } from './admin-dashboard.component'

const role = 'admin' // Just for the example
const comp = role === 'admin' ? AdminDashboardComponent : UserDashboardComponent

const routes: Routes = [
  { path: '', component: comp },
]

但是,假设我们想从 API 中检索角色,因此是异步的。有什么方法可以做到这一点?

4

6 回答 6

9

您可以创建一个 generic.module.ts,它将在声明数组中包含两个组件:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UserDashboardComponent }  from './user-dashboard.component'
import { AdminDashboardComponent } from './admin-dashboard.component    

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ UserDashboardComponent,AdminDashboardComponent ]
})
export class GenericModule { }

这样,您将拥有一个包含要加载的模块的模块。

现在下一步将是使用编译器异步加载它们:在您的组件内部执行以下操作:

import {GenericModule} from './generic.module';
import { Component, Input,ViewContainerRef, Compiler, NgModule,ModuleWithComponentFactories,OnInit,ViewChild} from '@angular/core';
@Component({
  selector: 'generic',
  template: '<div #target></div>'
})
export class App implements AfterViewInit {
  @ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;

  constructor(private compiler: Compiler) {}

  ngAfterViewInit() {
    this.createComponent('<u>Example template...</u>');
  }

  private createComponent(template: string,role:string) {
    @Component({template: template});
    const mod = this.compiler.compileModuleAndAllComponentsSync(GenericModule);
    const factory = mod.componentFactories.find((comp) =>
    //you can add your comparison condition here to load the component
    //for eg. comp.selector===role where role='admin'
    );
    const component = this.target.createComponent(factory);
  }
}

希望这可以帮助。

于 2016-10-04T15:17:26.057 回答
8

Angular 2 支持模块级别的延迟加载。功能模块是异步加载的,而不是组件。您可以制作该组件功能模块。 https://angular.io/docs/ts/latest/guide/ngmodule.html

于 2016-09-25T16:19:21.590 回答
4

您可以只定义一个更高级别的组件 fe DashboardComponent ,它包含在 route /dashboards

然后,父组件应该根据异步条件在其模板中加载子组件。

这样,您还需要使用 *ngIf 但至少它不会弄乱子组件模板。

于 2016-09-30T11:02:40.077 回答
4

由于您将为任一组件使用一个路由,因此一种解决方案是为该路由创建另一个组件,然后其模板可以引用这两个组件,但使用 ngIf 如下所示:

<user-dashboard *ngIf="role==='user'"></user-dashboard>
<admin-dashboard *ngIf="role==='admin'"></admin-dashboard>
于 2016-10-14T13:42:47.590 回答
1

我建议您使用路由器的导航方法以编程方式进行导航。因此,您在路由器文件中列出所有可能的路由。然后在您的组件中根据具体情况调用 router.navigate() 。

于 2016-09-25T18:26:15.790 回答
0

非常好的解决方案可能是“使用 auth-guard”。您可以尝试实现接口 CanActivate/CanLoad 并将您的条件放在该类中。

根据条件,路由被激活。

例子:

import { Injectable }       from '@angular/core';
import {
  CanActivate,
  ActivatedRouteSnapshot,
  RouterStateSnapshot
}                           from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';

@Injectable()
export class AuthorizationGuard implements CanActivate {
  constructor() {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): 
       Observable<boolean> {
    let url: string = state.url;
    return this.canbeLoaded(url);
  }

  canbeLoaded(url: string): Observable<boolean> {
    return Observable.of(true);  //put your condition here
  }
}
于 2017-05-25T14:25:23.270 回答