Как изменить свойство в компоненте stenciljs без запуска watch - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть компонент со свойством viewport. Я хочу прослушать изменения этого свойства, выполнить некоторые вычисления и отразить возможное измененное значение обратно в свойство. Моя первая попытка выглядела примерно так:

class MyComponent {
  @Prop()
  viewport: ViewportData

  @Watch('viewport)
  viewportChanged(newValue: ViewportData, oldValue:ViewportData) {
    ... do some calculations

    // Reflect value back as property
    this.viewport = computedViewport;
  }
}

Это приводит к переполнению стека, потому что отражение возвращаемого значения запускает еще один вызов функции наблюдения. Я мог бы предотвратить это, имея флаг, говорящий, является ли это внутренним изменением или нет. Примерно так:

class MyComponent {
  internalViewportChange = false;

  @Prop()
  viewport: ViewportData

  @Watch('viewport)
  viewportChanged(newValue: ViewportData, oldValue:ViewportData) {
    if (this.internalViewportChange) {
      this.internalViewportChange = false;
      return;
    }

    ... do some calculations

    // Reflect value back as property
    this.internalViewportChange = true;
    this.viewport = computedViewport;
  }
}

Мне не нравится этот подход. И ищет что-то лучшее. Эту проблему обычно можно решить с помощью методов получения и установки и закрытой переменной, сохраняющей фактическое состояние:

class MyComponent {
  private _viewport: ViewportData

  get viewport() {
    return this._viewport;
  }

  set viewport() {
    ... do some calculations

    // Reflect value back as property
    this.viewport = computedViewport;
  }
}

Однако, используя Stenciljs, геттеры и сеттеры генерируются автоматически. Есть хорошие идеи?

1 Ответ

0 голосов
/ 10 сентября 2018

Я бы, наверное, нарушил настройку двухсторонней опоры и создать однонаправленный поток данных и вместо этого генерировать события. Что-то вроде:

class MyComponent
  @Event() viewportChanged: EventEmitter;
  @Prop() viewport: ViewportData;
  @State() _computedViewport: ViewportData;

  @Watch('viewport') onViewportChanged(newValue) {
    // do calculations
    this._computedViewport = computedViewport;
    this.viewportChanged.emit(this._computedViewport);
  }

Внутренне вы будете работать только на _computedViewport, а общедоступная viewportProp доступна только для того, чтобы пользователи могли обновляться. Якобы вы могли бы также выставить @Method(), который делает то же самое.

...