【问题标题】:Angular2 : How to have the same guard for multiple componentsAngular2:如何为多个组件提供相同的防护
【发布时间】:2018-06-29 16:40:53
【问题描述】:

在 Angular2 中,是否有可能拥有可以应用于多个组件的相同防护(例如 CanActivate 或 CanDeactivate)?

这是MyComponent1 的守卫:

@Injectable()
export class MyGuard implements CanDeactivate<MyComponent1> {

  canDeactivate(component: MyComponent1): Promise<boolean> {
    // my code here
  }
}

我想为MyComponent2MyComponent3 等提供完全相同的保护。

我该如何实现呢?我需要按组件声明一个新的保护类,或者我可以重用我的类MyGuard 吗?

【问题讨论】:

    标签: angular angular2-routing


    【解决方案1】:

    只需将相同的防护添加到您希望应用它的每个路由。

    或者,您还可以创建一个无组件的父路由,在其中添加防护,所有子路由都将受到同一个防护的保护。 这仅在组件都在同级路由中时才有效。

    Angular DI 不支持泛型类型参数。作为一种解决方法,这应该可以满足您的需求(尽管事件可能比您想要的更详细):

    routes: [
      { path: 'x', component: MyComponent1, canDeactivate: [new Inject('CanDeactivateMyComponent1') },
      { path: 'y', component: MyComponent2, canDeactivate: [new Inject('CanDeactivateMyComponent2') },
    
    ]
    
    
    @NgModule({
      providers: [
        {provide: 'CanDeactivateMyComponent1', useFactory: () => new CanDeactivate<MyComponent1>()},
        {provide: 'CanDeactivateMyComponent2', useFactory: () => new CanDeactivate<MyComponent2>()},
    
      ],
    })
    export class AppModule {}
      ...
    })
    

    【讨论】:

    • 我认为@ElJackiste 的疑问在于Guard 实现所需的类型。这是一个很好的答案,但也许不是他正在等待的那种答案。
    • 拥有CanDeactivate&lt;MyComponent1&gt; 的事实不会阻止该组件的保护类MyComponent1 ?
    • 没有看到通用参数。因此,您需要专门针对应用防护的组件的防护的不同实例。您需要提供不同的实例。我会更新我的答案。
    • 谢谢。使用此解决方案,我不明白我在哪里定义 MyGuard 代码?
    • 如何编写相同的测试?
    【解决方案2】:

    路线:

    routes: [
        { path: 'x', component: MyComponent1, canDeactivate: ['MyGuard '] },
        { path: 'y', component: MyComponent2, canDeactivate: ['MyGuard '] },
    ]
    

    后卫:

    @Injectable()    
    export class MyGuard implements CanDeactivate<MyComp1 | MyComp2> {    
        constructor() { }    
    
      canDeactivate(    
        component: PermissionSetsComponent | NodeAccessGroupComponent,    
        ): Observable<boolean> | Promise<boolean> | boolean {    
    
     // Your code here    
     }    
    }
    

    【讨论】:

    • 在 Angular9 上仍然如此。不要试图将组件放在 canDeactivate() 不同的行上 - 这个答案是正确的语法(都在通用 component 下)。如果您需要从多个组件中获取方法到 Guard,请将它们粘贴在 constructor() 中 - 我重复一遍,而不是在 canDeactivate() 下;不管用。谢谢@Candice Moore。
    • 毕竟.. Angular 的CanDeactivate 服务实现中的constructor() 不能有任何参数... Guard 会默默地停止工作...
    • 如何编写相同的测试?我们需要为所有这些创建模拟吗?
    【解决方案3】:

    基于Günter Zöchbauer's answer,我有一个解决方案。

    后卫:

    @Injectable()
    export class MyGuard<T> implements CanDeactivate<T> {
      // Maybe some DI here, just inject them into useFactory and deps
      constructor() {}
    
      canDeactivate(component: T): Promise<boolean> {
        // my code here
      }
    }
    

    只要提供你的保护:

    routes: [
      { path: 'x', component: MyComponent1, canDeactivate: ['CanDeactivateMyComponent1'] },
      { path: 'y', component: MyComponent2, canDeactivate: ['CanDeactivateMyComponent2'] },
    
    ]
    
    
    @NgModule({
      providers: [
        {provide: 'CanDeactivateMyComponent1', useFactory: () => new MyGuard<MyComponent1>()},
        {provide: 'CanDeactivateMyComponent2', useFactory: () => new MyGuard<MyComponent2>()},
    
      ],
    })
    export class AppModule {}
      ...
    })
    

    【讨论】:

      【解决方案4】:

      这很冗长,但另一种方法是使用继承来创建一个新的专业守卫。

      我的通用守卫看起来像这样:

      // this goes on the component itself
      export interface IUnsavedChangesComponent
      {
          hasUnsavedChanges(): boolean;
      } 
      
      @Injectable()
      export class SaveFormsGuard<C extends IUnsavedChangesComponent> implements CanDeactivate<C>
      {
          constructor()
          {
              console.log("SAVEFORMSGUARD");
          }
      
          canDeactivate(component: C)
          {
              var hasUnsavedChanges = component.hasUnsavedChanges();
      
              ... dialog box logic ...
      
              return !hasUnsavedChanges;
          }
      }
      

      所以我创建了新的守卫

      export class SaveFormsGuard_OrderEditor extends SaveFormsGuard<OrderEditorComponent> { }
      export class SaveFormsGuard_CustomerEditor extends SaveFormsGuard<CustomerEditorComponent> { }
      

      您仍然必须将它们都放在提供程序列表中,因此它并没有像我希望的那样简化 - 但如果您还需要扩展您的逻辑中的逻辑,这可能是一个很好的模式以其他方式保护。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-07
        • 2022-12-31
        • 1970-01-01
        • 2017-12-07
        相关资源
        最近更新 更多