Props и реактивность

Stencil — это современный фреймворк для создания веб-компонентов, который использует принципы реактивности и позволяет легко интегрировать компоненты в любые приложения. В основе работы компонентов лежат props (свойства), которые передаются родительскими компонентами в дочерние. Эти свойства могут быть реактивными, что позволяет компонентам автоматически обновляться при изменении данных.

Основы Props

Props в Stencil представляют собой входные данные, которые компонент получает извне. Эти данные можно использовать для настройки поведения или отображения компонента. В отличие от обычных атрибутов в HTML, props в Stencil могут быть не только простыми значениями, но и сложными объектами, массивами или функциями.

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {
  @Prop() name: string;

  render() {
    return <div>Hello, {this.name}!</div>;
  }
}

В этом примере свойство name передается компоненту как prop. Значение пропса будет использоваться для отображения текста внутри элемента div. Этот компонент может быть использован в другом месте следующим образом:

<my-component name="John"></my-component>

Свойство name будет передано в компонент как строка “John”, и текст внутри компонента отобразится как «Hello, John!».

Декоратор @Prop

Декоратор @Prop() используется для объявления свойства компонента. Это позволяет Stencil автоматически отслеживать изменения значений пропсов и обновлять компонент в случае изменений. Каждый prop по умолчанию является непосредственно связанным с DOM-атрибутом и имеет свойство, соответствующее этому атрибуту в компоненте.

@Component({
  tag: 'my-toggle',
  styleUrl: 'my-toggle.css',
  shadow: true
})
export class MyToggle {
  @Prop() isOn: boolean;

  render() {
    return (
      <button>{this.isOn ? 'ON' : 'OFF'}</button>
    );
  }
}

В данном случае свойство isOn контролирует состояние кнопки и изменяет текст внутри кнопки в зависимости от своего значения. Это позволяет гибко взаимодействовать с компонентами.

Реактивность Prop в Stencil

Props в Stencil по своей сути являются реактивными. Это означает, что если значение пропса изменяется, Stencil автоматически перерисовывает компонент, чтобы отобразить новые данные. Реактивность играет ключевую роль в обеспечении динамического поведения компонентов и их взаимодействия с состоянием приложения.

Пример реактивного свойства:

@Component({
  tag: 'counter',
  styleUrl: 'counter.css',
  shadow: true
})
export class Counter {
  @Prop() count: number = 0;

  render() {
    return (
      <div>
        <span>{this.count}</span>
      </div>
    );
  }
}

В этом примере значение count будет обновляться при изменении пропса, и компонент автоматически перерисует отображение. Реактивность может быть полезной при работе с динамическими данными, которые обновляются через взаимодействие с пользователем, например, в случае с компонентами формы или кнопками.

Управление изменением Props

Stencil использует механизм реактивности, основанный на системе отслеживания изменений, который обновляет компоненты только при необходимости. Однако можно управлять изменениями пропсов и явно указать, как реагировать на изменение их значений, используя метод жизненного цикла componentWillUpdate.

@Component({
  tag: 'watcher-component',
  styleUrl: 'watcher-component.css',
  shadow: true
})
export class WatcherComponent {
  @Prop() value: number;

  componentWillUpdate() {
    console.log('Component will update due to prop change');
  }

  render() {
    return <div>{this.value}</div>;
  }
}

Этот метод жизненного цикла позволяет отслеживать изменения пропса и выполнять дополнительные действия перед тем, как компонент обновится.

Синхронизация Props с состоянием компонента

В Stencil можно синхронизировать props с состоянием компонента. Это полезно в случае, если prop передается извне, но компонент должен вести дополнительное состояние внутри себя, которое зависит от пропса.

@Component({
  tag: 'sync-component',
  styleUrl: 'sync-component.css',
  shadow: true
})
export class SyncComponent {
  @Prop() initialValue: number;
  @State() currentValue: number;

  componentWillLoad() {
    this.currentValue = this.initialValue;
  }

  handleChange(event) {
    this.currentValue = event.target.value;
  }

  render() {
    return (
      <div>
        <input type="number" value={this.currentValue} onIn put={(event) => this.handleChange(event)} />
        <p>Current Value: {this.currentValue}</p>
      </div>
    );
  }
}

Здесь компонент принимает prop initialValue, который используется для первоначальной установки состояния currentValue. При изменении значения в поле ввода, состояние компонента обновляется, что ведет к повторному рендерингу.

Watchers: Наблюдатели за изменением Props

Stencil позволяет добавлять наблюдателей за изменениями пропсов с помощью декоратора @Watch(). Этот декоратор позволяет отслеживать изменения значений и выполнять дополнительные действия при каждом изменении.

@Component({
  tag: 'watcher-example',
  styleUrl: 'watcher-example.css',
  shadow: true
})
export class WatcherExample {
  @Prop() propValue: number;

  @Watch('propValue')
  watchPropValue(newValue: number, oldValue: number) {
    console.log(`propValue changed from ${oldValue} to ${newValue}`);
  }

  render() {
    return <div>Prop value is: {this.propValue}</div>;
  }
}

В этом примере каждый раз, когда значение propValue изменяется, будет вызываться метод watchPropValue, и выводиться в консоль старое и новое значение пропса.

Заключение

Props в Stencil обеспечивают гибкость и мощь для создания динамичных и реактивных компонентов. Они позволяют передавать данные из родительских компонентов, обрабатывать изменения значений и обеспечивать согласованность между состоянием компонента и его визуальным представлением. Механизмы реактивности и наблюдателей за изменениями значений пропсов дают разработчикам инструменты для создания сложных интерфейсов с минимальными усилиями.