イベントは、Webコンポーネントで状態を通信するために不可欠です。 最新のブラウザで標準のイベントAPIをサポートすることに加えて、Polymerはイベント処理のより簡単な方法を提供します。 また、Polymerはデータバインディングに必要なイベントを自動的に処理します。

ポリマーのイベント

Polymerでは、通常のパターンは、プロパティを介して値を子コンポーネントに渡すことです。 また、イベントを使用して変更を親コンポーネントに渡します。

このパターンを説明するために、プロパティがダウンし、イベントがアップというフレーズがよく使用されます。 このパターンに従うことで、予測可能な方法で状態の変化を処理することが可能になります。

Properties go down, events go up

メディエーターパターン

メディエーターパターンは、メディエーターオブジェクトがその子オブジェクト間の通信を処理する動作パターンです。

このパターンは、ポリマーコンポーネントで使用することをお勧めします。 1つのメディエーターコンポーネント(例:my-component )子要素間の通信を処理します(例:inputh3 )。

注釈付きイベントリスナー

注釈付きのイベントリスナーを使用して、宣言的にイベントリスナーを作成できます

これは、ポリマープロパティを紹介する記事で使用しました。 on という名前のプロパティの後に、リッスンするイベント名を指定することで、子要素のイベントをリッスンできます。

<dom-module id="my-element">
  <template>
    ...
    <div>
      <button type="button" increment on-click="handleIncrement">+</button>
      <span>[[value]]</span>
      <button type="button" decrement on-click="handleDecrement">-</button>
    </div>
  </template>
  <script>
    class MyCounter extends Polymer.Element {
      static get is() { return 'my-counter'; }
      static get properties() {
        return {
          value: {
            type: Number,
            value: 0,
            reflectToAttribute: true,
          },
          increment: {
            type: Number,
            value: 1,
          }
        };
      }

      handleIncrement() {
        let incrementedValue = this.value + this.increment;
        this.value = this.isInRange(incrementedValue) ? incrementedValue : this.value;
      }
    }
  </script>
</dom-module>

上記の例では、ボタンの子要素でclickイベントが発生したときに、handleIncrementメソッドを呼び出します。

イベントを聞く

Polymerコンポーネントでは、イベントをどのようにリッスンするかは、その発生源によって異なります。 さまざまな発生源からのイベントは、次の方法で処理されます。

  • カスタム要素–カスタム要素自体からのイベント。 ready関数にイベントリスナーを追加できます。
ready() {
  super.ready();
  this.addEventListener('click', this._onClick);
}
  • 子要素–カスタム要素の子要素からのイベント。 前に説明したように、注釈付きのイベントリスナーを使用できます。

  • Outside Elements –カスタム要素のスコープ外からのイベント(例:window)。 これらのイベントについては、connectedCallbackにイベントリスナーを追加できます。

constructor() {
  // we need to use handlers bound to the local 'this'
  // to ensure that the 'this' context is properly set
  _boundResizeHandler = resizeHandler.bind(this);
}

connectedCallback() {
  super.connectedCallback();
  window.addEventListener('resize', this._boundResizeHandler);
}

disconnectedCallback() {
  super.disconnectedCallback();
  // We must remove listeners to prevent memory leaks.
  window.removeEventListener('resize', this._boundResizeHandler);
}

_boundResizeHandler

resizeHandler(e) {
  // handle resize event here
  console.log('resized');
}

カスタムイベントの発火

新しいCustomEventを作成することにより、カスタムイベントを呼び出すことができます。 これは、最新のブラウザでカスタムイベントを作成する標準的な方法です。 Polymerは、古いブラウザをサポートするためのポリフィルも提供します。

const event = new CustomEvent('my-event', {bubbles: true, composed: true});

CustomEventに次の2つのプロパティを設定しています。

  • bubblesイベントがDOMを介してバブルすることを許可します。
  • composed Shadow DOM境界を介したバブリングを許可します。これをtrueに設定すると、イベントがメインDOMによってインターセプトされます。

イベントのリターゲティング

イベントがShadowDOMの内部からその親にバブルアップされると、そのイベントは再ターゲットになります。

親がカスタム要素自体をイベントのターゲットと見なすことを意味します。 カスタム要素内にある子要素によってイベントがトリガーされた場合でも。

Composed path for getting event target

これにより、Shadow DOMの構造を知らなくても、親コンポーネントがイベントを処理できるようになります。 しかし、実際のターゲットを見つける必要がある場合もあります。

ComposedPath

イベントの発生源を特定する必要がある場合は、composedPathプロパティを使用して特定できます。 event.composedPath()は、イベントがバブルスルーした要素の配列を返します。 返される配列の最初の項目はorigin要素です。