Angular2 @HostListener不适用于派生组件
我有一个基于Angular2的客户端应用程序.
我有一个基类: abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHandler() { console.log('bla'); } } 和两个非常相似的派生类: @Component({ selector: 'derived-one',templateUrl: './templates/app/+derived-one/derived-one.component.html' }) export class DerivedOne extends BaseClass { } @Component({ selector: 'derived-two',templateUrl: './templates/app/+derived-two/derived-two.component.html' }) export class DerivedTwo extends BaseClass { } 问题是,例如,在DerivedOne中,在DerivedTwo中,在UnloadHandler工作正常之前,它根本不接收调用. 我知道很难找到为什么只是查看上面的信息,但也许有人可能会怀疑可能导致这种奇怪行为的原因. 还有一些说明: 如果我使用以下内容: abstract class BaseClass constructor(){ window.onbeforeunload = function(){ console.log('bla'); } } } 一切正常,但我仍然想找到一个基于Angular2的解决方案; 如果我写 abstract class BaseClass { beforeUnloadHandler() { console.log('bla'); } } 在derived-two.component.html中 <div (window.beforeunload)="beforeUnloadHandler()"></div> 一切都很好,但它看起来像一个丑陋的黑客; 如果我写的话 abstract class BaseClass { beforeUnloadHandler() { console.log('bla'); } } 和 @Component({ selector: 'derived-two',host: {'window:beforeunload': 'beforeUnloadHandler' } templateUrl: './templates/app/+derived-two/derived-two.component.html' }) export class DerivedTwo extends BaseClass { } 它不会起作用. 最后,如果我在DerivedTwo和DerivedOne中使用@HostListener,它可以工作,但我想避免使用重复的代码. 希望上面的信息足以与之合作(至少要有一些猜测).
更新2.3.0
您现在可以利用组件的对象继承. 您可以在此提交https://github.com/angular/angular/commit/f5c8e0989d85bc064f689fc3595207dfb29413f4中看到更多详细信息 旧版 1)如果你有一个班级: abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHander() { console.log('bla'); } } 然后它会工作 Plunker Example(在编辑器和监视控制台的某处放置空格) 但要小心,因为Angular2不支持完全继承 – Issue with binding and @ViewChild
特别是如果您在派生组件上有属性装饰器,它将无法工作.例如,假设我们有以下代码: abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHander() { console.log(`bla-bla from${this.constructor.name}`); } } @Component({ selector: 'derived-one',template: '<h2>derived-one</h2>' }) export class DerivedOne extends BaseClass { @Input() test; } Plunker 它将被转换为javascript,如: var core_1 = require('@angular/core'); var BaseClass = (function () { function BaseClass() { } BaseClass.prototype.beforeUnloadHander = function () { console.log("bla-bla from" + this.constructor.name); }; __decorate([ core_1.HostListener('window:beforeunload'),__metadata('design:type',Function),__metadata('design:paramtypes',[]),__metadata('design:returntype',void 0) ],BaseClass.prototype,"beforeUnloadHander",null); return BaseClass; }()); var DerivedOne = (function (_super) { __extends(DerivedOne,_super); function DerivedOne() { _super.apply(this,arguments); } __decorate([ core_1.Input(),Object) ],DerivedOne.prototype,"test",void 0); DerivedOne = __decorate([ core_1.Component({ selector: 'derived-one',template: '<h2>derived-one</h2>' }),[]) ],DerivedOne); return DerivedOne; }(BaseClass)); 我们对以下几行感兴趣: __decorate([ core_1.HostListener('window:beforeunload'),void 0) ],null); ... __decorate([ core_1.Input(),Object) ],void 0); HostListener和Input是属性修饰符(propMetadata key).这种方式将定义两个元数据条目 – 在BaseClass和DerivedOne上 最后,当angular2从DerivedOne类中提取元数据时,它将只使用自己的元数据: 要获取所有元数据,您可以编写自定义装饰器,如: function InheritPropMetadata() { return (target: Function) => { const targetProps = Reflect.getMetadata('propMetadata',target); const parentTarget = Object.getPrototypeOf(target.prototype).constructor; const parentProps = Reflect.getMetadata('propMetadata',parentTarget); const mergedProps = Object.assign(targetProps,parentProps); Reflect.defineMetadata('propMetadata',mergedProps,target); }; }; @InheritPropMetadata() export class DerivedOne extends BaseClass { 这是一个有效的demo 2)如果你做了如下: abstract class BaseClass constructor(){ window.onbeforeunload = function(){ console.log('bla'); }; } } 然后它将只调用一次因为你每次都覆盖window.onbeforeunload处理程序 abstract class BaseClass { constructor(){ window.addEventListener('beforeunload',() =>{ console.log(`bla-bla from${this.constructor.name}`); }) } } Plunker Example 3)最后,如果您有基类,如下所示: abstract class BaseClass { beforeUnloadHander() { console.log(`bla-bla from${this.constructor.name}`); } } 然后你必须使用正确的语法(你错过了 host: {'(window:beforeunload)': 'beforeUnloadHander()' } Plunker Example 希望它能帮到你! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |