Angular 2:“全球”生命周期钩子?

时间:2016-09-09 21:55:54

标签: angular

TL; DR

我们正在使用Angular 2构建应用,并希望注册“全局”ngOnInitngOnDestroy功能。对于“全局”,我的意思是该函数是针对每个组件执行的,而不需要为每个组件显式实现。这可能吗?

详细

一些(但不是全部)组件需要在加载后在全局服务中注册一些内容(例如ngOnInit),并在卸载后再次注销(例如ngOnDestroy)。以下是我能想到的两种方法:

  • 在需要执行此操作的每个组件中实现此逻辑(在ngOnInitngOnDestroy中)。
  • 在基类中实现此逻辑,该基类调用由子类实现的抽象方法,这些子类指定了需要注册/未注册的内容。

这两种方法都不令人满意:

  • 首先,我需要一遍又一遍地实现整个逻辑。是的,我知道,我可以将“锅炉板” - 代码放在帮助器类或其他东西中。但它似乎有点隐含,“隐藏”在常规的Angular生命周期中。具有发言名称(例如接口/基类)似乎更明确。
  • 在第二个类中需要扩展相同的公共基类。但是,如果他们还应该扩展其他一些基类(多重继承)呢?

这就是我提出以下想法的原因:

为什么不用可以由所有必需组件实现的接口替换上面提到的抽象类。然后,我将注册一个全局函数,该函数在所有组件的每个ngOnInitngOnDestroy上执行(如果可能的话 - 例如在模块,路由等中?)。在函数中,我将检查组件是否实现了接口,如果是,则调用相应的函数以获取要注册的类型特定的东西。

我的问题

  • Angular 2可以这样做吗?即可以注册“全球生命周期钩子”(或类似的东西)吗?
  • 或者这是一种完全错误的方法吗?
  • 任何其他/更好的想法?

1 个答案:

答案 0 :(得分:5)

强制整个应用程序的行为不是一个好主意,这会影响第三方组件以及初学者。

Boilerplate代码可以移动到具体的基类中。存在用于JS / TS多重继承的解决方案,例如, @mixin,另见TypeScript guide

由于基类方法是固定的,因此类mixin可以表示为简化的装饰器:

class CustomLifecycle implements OnInit, OnDestroy  {
  constructor(
    public originalNgOnInit: Function,
    public originalNgOnDestroy: Function
  ) {}

  ngOnInit() {
    ...
    if (typeof this.originalNgOnInit === 'function') {
      this.originalNgOnInit();
    }
  }

  ngOnDestroy() {
    ...
    if (typeof this.originalNgOnDestroy === 'function') {
      this.originalNgOnDestroy ();
    }
  }
}

function Lifecycled() {
  return function (target: Function) {
    const customLifecycle = new CustomLifecycle(
      target.prototype.ngOnInit,
      target.prototype.ngOnDestroy
    );

    target.prototype.ngOnInit = customLifecycle.ngOnInit;
    target.prototype.ngOnDestroy = customLifecycle.ngOnDestroy;
  }
}

它可以像

一样使用
@Component({ ... })
@Lifecycled()
class SomeComponent { .... }

实现仅限于ngOnInit等原型方法,箭头成员需要修补构造函数。