gpt4 book ai didi

angular - 将多个主机绑定(bind)组合成一个装饰器

转载 作者:太空狗 更新时间:2023-10-29 17:35:17 24 4
gpt4 key购买 nike

我的组件使用主机绑定(bind)装饰器来显示组件选择器,以便它们占据所有可用宽度:

@HostBinding('style.width.%')
@HostBinding('style.height.%')
private readonly SIZE = 100;

@HostBinding('style.display')
private readonly DISPLAY = 'block';

@HostBinding('style.box-sizing')
private readonly BOX_MODEL = 'border-box';

我想做的是创建一个包含所有这些装饰器的装饰器(在类或属性级别,我不在乎),这样我就不必每次都重写它。

现在,我通过创建一个父类(super class)并让我的其他类扩展它来使其工作,但它有很多限制和不便,因此我的问题。

任何帮助,即使是文档,也非常感谢!

编辑 我也找到了this SOF question ,但我的问题的不同之处在于变量具有值,而且我似乎无法找到如何将这些值传递给我的装饰器。

EDIT 2 解释我的需求:我有这个组件

@Component(...)
export class MyAngularComponent extends HostBinderComponent {...}

还有这个

export class HostBinderComponent {
@HostBinding('style.width.%')
@HostBinding('style.height.%')
private readonly SIZE = 100;

@boxComponent()
private readonly DISPLAY;

@HostBinding('style.box-sizing')
private readonly BOX_MODEL = 'border-box';
}

我的最终目标是删除父类(super class)并拥有类似

的东西
@Component(...)
@BoxComponent()
export class MyAngularComponent {...}

这样我就不必再在 Angular 组件中使用 extendsHostBinding 了!

最佳答案

应用装饰器涉及调用 __decorate 辅助函数。此函数可以由编译器生成,也可以从自定义 tslib 中使用。 Angular 将 tslib 模块用于 __decorate 函数,我们可以从那里使用 __decorate。 (我们可以复制 ts 生成的版本或编写我们自己的调用装饰器函数的更简单版本的 __decorate,但最好只使用与框架使用的调用装饰器相同的方式)

有了这个函数(并且在检查了 TS 如何为字段调用装饰器之后)我们可以轻松地创建我们自己的复合装饰器:

import { __decorate } from 'tslib';


function BoxHostBindings() {
return function(target) {
__decorate([
HostBinding('style.width.%'),
HostBinding('style.height.%'),
], target.prototype, "SIZE", void 0);
__decorate([
HostBinding('style.display'),
], target.prototype, "DISPLAY", void 0);
__decorate([
HostBinding('style.box-sizing'),
], target.prototype, "BOX_MODEL", void 0);
}
}

注意:我没有对此进行过广泛测试,但似乎有效,而且我希望它有效。

用法:

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
@BoxHostBindings()
export class AppComponent {
title = 'testapp';

private readonly SIZE = 100;
private readonly DISPLAY = 'block'
private readonly BOX_MODEL = 'border-box';
}

编辑

为属性设置值有点困难。我们无法轻松访问构造函数的执行,因此我们不能这样做。

一个选项是在 prototype 上定义值,因为这些值是只读的,这应该可以正常工作:

function BoxHostBindings(size: number, display: string, box_model: string) {
return function(target) {
target.prototype.SIZE = size;
target.prototype.DISPLAY = display;
target.prototype.BOX_MODEL = box_model;
__decorate([
HostBinding('style.width.%'),
HostBinding('style.height.%'),
], target.prototype, "SIZE", void 0);
__decorate([
HostBinding('style.display'),
], target.prototype, "DISPLAY", void 0);
__decorate([
HostBinding('style.box-sizing'),
], target.prototype, "BOX_MODEL", void 0);
}
}

我们还可以定义属性以允许用户修改值,并将其存储在字段('_' + 名称)中,但如果值未定义则返回默认值:

function BoxHostBindings(size: number, display: string, box_model: string) {
return function(target) {
function propHelper(name: string, defaultValue: any) {
Object.defineProperty(target.prototype, name, {
get: function () {
return this['_' + name] || defaultValue;
},
set: function(value: any ) {
this['_' + name] = value
},
enumerable: true,
configurable: true
});
}
propHelper("SIZE", size);
propHelper("DISPLAY", display);
propHelper("BOX_MODEL", box_model);
__decorate([
HostBinding('style.width.%'),
HostBinding('style.height.%'),
], target.prototype, "SIZE", void 0);
__decorate([
HostBinding('style.display'),
], target.prototype, "DISPLAY", void 0);
__decorate([
HostBinding('style.box-sizing'),
], target.prototype, "BOX_MODEL", void 0);
}
}

关于angular - 将多个主机绑定(bind)组合成一个装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53744981/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com