Dmi*_*kov 6 typescript angular2-template angular
我有一个基于Angular2的客户端应用程序.我有一个基类:
abstract class BaseClass {
@HostListener('window:beforeunload') beforeUnloadHandler() {
console.log('bla');
}
}
Run Code Online (Sandbox Code Playgroud)
和两个非常相似的派生类:
@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 {
}
Run Code Online (Sandbox Code Playgroud)
问题在于,例如,DerivedOne beforeUnloadHandler工作正常,而在DerivedTwo其中根本不接收电话.
我知道很难找到为什么只是查看上面的信息,但也许有人可能会怀疑可能导致这种奇怪行为的原因.
还有一些说明:
如果我使用以下内容:
abstract class BaseClass
constructor(){
window.onbeforeunload = function(){
console.log('bla');
}
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常,但我仍然想找到一个基于Angular2的解决方案;
如果我写
abstract class BaseClass {
beforeUnloadHandler() {
console.log('bla');
}
}
Run Code Online (Sandbox Code Playgroud)
并在 derived-two.component.html
<div (window.beforeunload)="beforeUnloadHandler()"></div>
Run Code Online (Sandbox Code Playgroud)
一切都很好,但它看起来像一个丑陋的黑客;
如果我写的话
abstract class BaseClass {
beforeUnloadHandler() {
console.log('bla');
}
}
Run Code Online (Sandbox Code Playgroud)
和
@Component({
selector: 'derived-two',
host: {'window:beforeunload': 'beforeUnloadHandler' }
templateUrl: './templates/app/+derived-two/derived-two.component.html'
})
export class DerivedTwo extends BaseClass {
}
Run Code Online (Sandbox Code Playgroud)
它不会起作用.
最后,如果我使用@HostListenerin DerivedTwo和in DerivedOne,它可以工作,但我想避免使用重复的代码.
希望上面的信息足以与之合作(至少要有一些猜测).
yur*_*zui 10
更新2.3.0
您现在可以利用组件的对象继承.
您可以在此提交中看到更多详细信息https://github.com/angular/angular/commit/f5c8e0989d85bc064f689fc3595207dfb29413f4
旧版
1)如果你有一个班级:
abstract class BaseClass {
@HostListener('window:beforeunload') beforeUnloadHander() {
console.log('bla');
}
}
Run Code Online (Sandbox Code Playgroud)
然后它会工作
Plunker示例(在编辑器和监视控制台的某处放置空格)
但要小心,因为Angular2不支持完全继承 - 绑定问题和@ViewChild
但仍然不清楚为什么@HostListener的解决方案首先不起作用
特别是如果您在派生组件上有属性装饰器,它将无法工作.例如,假设我们有以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
它将被转换为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(),
__metadata('design:type', Object)
], DerivedOne.prototype, "test", void 0);
DerivedOne = __decorate([
core_1.Component({
selector: 'derived-one',
template: '<h2>derived-one</h2>'
}),
__metadata('design:paramtypes', [])
], DerivedOne);
return DerivedOne;
}(BaseClass));
Run Code Online (Sandbox Code Playgroud)
我们对以下几行感兴趣:
__decorate([
core_1.HostListener('window:beforeunload'),
__metadata('design:type', Function),
__metadata('design:paramtypes', []),
__metadata('design:returntype', void 0)
], BaseClass.prototype, "beforeUnloadHander", null);
...
__decorate([
core_1.Input(),
__metadata('design:type', Object)
], DerivedOne.prototype, "test", void 0);
Run Code Online (Sandbox Code Playgroud)
HostListener并且Input是物业装饰者(propMetadata关键).这种方式将定义两个元数据条目 - on BaseClass和onDerivedOne

最后,当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 {
Run Code Online (Sandbox Code Playgroud)
这是一个有效的演示
2)如果你做了如下:
abstract class BaseClass
constructor(){
window.onbeforeunload = function(){
console.log('bla');
};
}
}
Run Code Online (Sandbox Code Playgroud)
然后它将只被调用一次,因为你window.onbeforeunload每次都要覆盖处理程序你应该使用以下代码:
abstract class BaseClass {
constructor(){
window.addEventListener('beforeunload', () =>{
console.log(`bla-bla from${this.constructor.name}`);
})
}
}
Run Code Online (Sandbox Code Playgroud)
3)最后,如果您有基类,如下所示:
abstract class BaseClass {
beforeUnloadHander() {
console.log(`bla-bla from${this.constructor.name}`);
}
}
Run Code Online (Sandbox Code Playgroud)
那么你必须在decorator属性中使用正确的语法(你缺少括号):
host: {'(window:beforeunload)': 'beforeUnloadHander()' }
Run Code Online (Sandbox Code Playgroud)
希望它能帮到你!
| 归档时间: |
|
| 查看次数: |
3122 次 |
| 最近记录: |