Применение декоратора включает вызов вспомогательной функции __decorate
.Эта функция может быть сгенерирована компилятором или использована из пользовательского tslib.Angular использует модуль tslib
для функции __decorate
, и мы можем использовать __decorate
оттуда.(Мы могли бы скопировать версию, сгенерированную ts, или написать нашу собственную более простую версию __decorate
, которая вызывает функцию декоратора, но лучше всего использовать тот же способ вызова декораторов, что и фреймворк)
Armedс помощью этой функции (и после проверки того, как 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);
}
}