首页 > 解决方案 > Angular:如何获取默认的@Input 值?

问题描述

我们正在开发组件,在使用它们时,我们希望使用与 DOM 节点相同的机制来有条件地定义属性。因此,为了防止属性出现,我们将值设置为 null 并且它在最终的 HTML 输出中不存在。伟大的!

<button [attr.disabled]="condition ? true : null"></button>

现在,当使用我们自己的组件时,这是行不通的。当我们设置 时null,我们实际上null将组件 @Input 作为值。任何默认设置值都将被覆盖。

...
@Component({
    selector: 'myElement',
    templateUrl: './my-element.component.html'
})

export class MyElementComponent {
    @Input() type: string = 'default';
...
<myElment [type]="condition ? 'something' : null"></myElement>

因此,每当我们在组件中读取时type,我们得到null的不是设置的'default'值。

我试图找到一种方法来获取原始默认值,但没有找到。它存在于及时ngBaseDef访问constructor时,但这在生产中不起作用。我希望ngOnChanges在完成的第一个更改中给我真正的(默认)值,因此能够防止它被null设置,但是.previousValueundefined

我们想出了一些方法来解决这个问题:

<myElement #myelem [type]="condition ? 'something' : myelem.type"></myElement>
_type: string = 'default';
@Input()
set type(v: string) {if (v !== null) this._type = v;}
get type() { return this._type; }

但很好奇,是否还有其他人有类似的问题以及它是如何解决的。我也很欣赏任何其他可能更优雅的想法。

谢谢!

标签: javascriptangular

解决方案


没有标准的角度方式,因为很多时候你会想要nullundefined作为价值。你的想法不是坏的解决方案。我还有几个

  1. 我想你也可以使用这个ngOnChanges钩子:
@Input()
type: string = 'defaultType';

ngOnChanges(changes: SimpleChanges): void {
 // == null to also match undefined
 if (this.type == null) {
    this.type = 'defaultType';
  }
}
  1. 或使用Observables
private readonly _type$ = new BehaviorSubject('defaultType');

readonly type$ = this._type$.pipe(
  map((type) => type == null ? 'defaultType' : type)
); 

@Input()
set type(type: string) {
  this._type$.next(type);
}
  1. 或创建自己的装饰者游乐场
function Default(value: any) {
  return function(target: any, key: string | symbol) {
    const valueAccessor = '__' + key.toString() + '__';

    Object.defineProperty(target, key, {
      get: function () {
        return this[valueAccessor] != null ? this[valueAccessor] : value
      },
      set: function (next) {
        if (!Object.prototype.hasOwnProperty.call(this, valueAccessor)) {
          Object.defineProperty(this, valueAccessor, {
            writable: true,
            enumerable: false
          });
        }

        this[valueAccessor] = next;
      },
      enumerable: true
    });
  };
}

您可以像这样使用它:

@Input()
@Default('defaultType')
type!: string;

推荐阅读