将多个主机绑定合并为一个单独的修饰符 [英] Combine several host bindings into one single decorator

查看:12
本文介绍了将多个主机绑定合并为一个单独的修饰符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一些组件使用主机绑定修饰符来显示组件选择器,以便它们具有所有可用宽度:

@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';

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

现在,我通过创建一个超类并让我的其他类扩展它来使它工作,但它有很多限制和不便,因此我提出了这个问题。

任何帮助,即使是文档,我们都非常感激!

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

编辑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';
}

我的最终目标是删除超类并拥有类似

的内容
@Component(...)
@BoxComponent()
export class MyAngularComponent {...}

这样我就不必再在角度组件中使用extendsHostBinding

推荐答案

应用修饰符涉及调用__decorate帮助器函数。该函数可以由编译器生成,也可以从定制的tslb中使用。Angel对__decorate函数使用tslib模块,我们可以从那里使用__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);
  }
}

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

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);
  }
}

这篇关于将多个主机绑定合并为一个单独的修饰符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆