首页 > 解决方案 > 如何在 StencilJS 中使用 getter/setter 处理 @Prop() 逻辑

问题描述

我想在我的 StencilJS 组件中添加一个 getter / setter。正如我目前所知,您不能将 get/set 逻辑与@Prop(). 如何在 StencilJS 组件中生成类似的逻辑?

例如,假设我有以下Angular组件,我可以执行以下操作:

  @Input()
  get enabled(): boolean {
    return this._enabledOverride == null ? this._getDefaultEnabled() : this.enabledOverride;
  }
  set enabled(value: boolean) {
    this._enabledOverride = coerceBooleanProperty(value);
  }

  _enabledOverride: boolean|null = null;

  private _getDefaultEnabled() {
    return this.stepControl ? this.stepControl.valid && this.interacted : this.interacted;
  }

我对 StencilJS 组件的尝试如下:

子组件

  _enabled: boolean;

  @Prop() enabled: boolean;

  @Watch('enabled')
  watchHandler(newValue: boolean, oldValue: boolean) {
    this._enabledOverride = coerceBooleanProperty(newValue);
    this._enabled = this._enabledOverride == null ? this.getDefaultEnabled() : this._enabledOverride;
  }

  _enabledOverride: boolean | null = null;

在这里,我Watchenabled更改、执行逻辑并将私有实例变量设置_enabled为更新的值。这很棒,可以在实例中使用。但是,如果我需要enabled从父组件访问该属性,我的逻辑也不会在页面加载时运行,因为 @Watch() 不会在页面加载时触发。一旦它运行,现在 和 之间的值不enabled匹配_enabled。因此,例如在我的父组件中,如果我有:

父组件

export class Parent {
  @Element() el: HTMLElement;

  componentWillLoad() {
    const childElements = this.el.querySelectorAll('app-child-component');
    childElements.forEach((el) => {
      // attempting to access the enabled property would be out of sync with the private _enabled
      console.log(el.enabled)
    })
  }
}

如上所示,尝试访问 enabled 属性将与私有 _enabled 不同步,从而给我一个过时的属性值。我该怎么办?谢谢!

标签: stenciljs

解决方案


您可以使用装饰器添加一个方法@Method来充当 getter:

@Method()
async getEnabled() {
  return this._enabledOverride == null ? this._getDefaultEnabled() : this.enabledOverride;
}

然后像这样使用它

const childElements = this.el.querySelectorAll('app-child-component');

await Promise.all(
  childElements.map(async el => console.log(await el.getEnabled()))
)

推荐阅读