Polymerは、一般的なデータバインディングのユースケースに備えて各種カスタム要素を提供しています。:
- テンプレートリピーター(
dom-repeat
):配列アイテムごとに、テンプレートのコンテンツでインスタンスを生成します。 - 配列セレクタ:構造化されたデータの配列において選択状態を管理します。
- 条件付きテンプレート(
dom-if
):指定された条件がtrue
なら、そのコンテンツをスタンプします。 - 自動バインディングテンプレート(
dom-bind
):Polymer要素外部でデータバインディングが利用できます。
2.0向けのヒント:データバインディングのヘルパー要素は、下位バージョンと互換性のある
polymer.html
をインポートする際にバンドルされています。レガシーなインポートを利用しない場合、あなたが使用したヘルパー要素を個別にインポートする必要があります。
テンプレートリピーター(dom-repeat)
テンプレートリピーターは、配列のバインドに特化したテンプレートです。配列内の各アイテムごとに、テンプレートのコンテンツのインスタンスを一つ生成します。各インスタンスは、次のプロパティを含む新たな[データバインディングのスコープ](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#data-binding-scope)を作成します。:
-
item
:インスタンスの作成に使用された配列のアイテム -
index
:配列内のitem
のインデックス(配列がソートまたはフィルタリングされると、index
の値は変化します)
テンプレートリピーターを利用するには二つの方法があります。:
-
Polymer要素内またはPolymerが管理する他のテンプレートの内では、
<template is="dom-repeat>
という省略記法を使用してください。<template is="dom-repeat" items="{{items}}"> ... </template>
-
Polymerが管理するテンプレートの外側では、ラッパー要素
<dom-repeat>
を使用します。<dom-repeat> <template> ... </template> </dom-repeat>
このフォームでは、通常、プロパティ
items
を命令的に設定します。:var repeater = document.querySelector('dom-repeat'); repeater.items = someArray;
Polymerが管理するテンプレートには、Polymer要素のテンプレートや、dom-bind
、dom-if
、dom-repeat
に属するテンプレート、あるいはTemplatizer
によって管理されるテンプレートが含まれます。
ほとんどのケースにおいて、dom-repeat
には、一番目(省略形)のフォームを使用することになるでしょう。
テンプレートリピーターは後方互換性を確保するため、レガシーなインポート(polymer.html
)によって取り込まれます。もしpolymer.html
をインポートしない場合は、次のコードに示すようdom-repeat.html
をインポートして下さい。
例:
<link rel="import" href="components/polymer/polymer-element.html">
<! -- import template repeater -->
<link rel="import" href="components/polymer/src/elements/dom-repeat.html">
<dom-module id="x-custom">
<template>
<div> Employee list: </div>
<template is="dom-repeat" items="{{employees}}">
<div># [[index]]</div>
<div>First name: [[item.first]]</span></div>
<div>Last name: [[item.last]]</span></div>
</template>
</template>
<script>
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
employees: {
type: Array,
value() {
return [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'},
];
}
}
}
}
}
customElements.define(XCustom.is, XCustom);
</script>
</dom-module>
item
のサブプロパティの変更通知は、テンプレートのインスタンスに転送され、一般的な[変更通知イベント](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#change-notification-events)を使用して更新されます。配列items
が双方向バインディングデリミタを使ってバインドされている場合、個々のアイテムの変更を上に向けて流すこともできます。
テンプレートリピーターが変更を反映するには、配列items
を監視できるように更新する必要があります。例えば:
// Use Polymer array mutation methods:
this.push('employees', {first: 'Diana', last: 'Villiers'});
// Use Polymer set method:
this.set('employees.2.last', 'Maturin');
// Use native methods followed by notifyPath
this.employees.push({first: 'Barret', last: 'Bonden'});
this.notifyPath('employees');
詳細については、[オブジェクトと配列を監視可能に変更する](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#mutating-objects-and-arrays-observably)を参照してください。
dom-repeat
テンプレート内のイベントの処理
dom-repeat
テンプレートのインスタンスから生成されたイベントを処理する際、イベントが発生した要素と、アイテムを生成したモデルデータをマッピングしたいことが頻繁にあるかもしれません。
<dom-repeat>
テンプレートの内部に宣言型イベントハンドラを追加すると、リピーターはリスナーに送られてきた各イベントにmodel
プロパティを付加します。model
オブジェクトには、テンプレートのインスタンスを生成するのに使用したスコープデータが含まれており、アイテムのデータはmodel.item
になります。
<link rel="import" href="polymer/polymer-element.html">
<link rel="import" href="polymer/src/elements/dom-repeat.html">
<dom-module id="x-custom">
<template>
<template is="dom-repeat" id="menu" items="{{menuItems}}">
<div>
<span>{{item.name}}</span>
<span>{{item.ordered}}</span>
<button on-click="order">Order</button>
</div>
</template>
</template>
<script>
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
menuItems: {
type: Array,
value() {
return [
{name: 'Pizza', ordered: 0},
{name: 'Pasta', ordered: 0},
{name: 'Toast', ordered: 0}
];
}
}
}
}
order(e) {
e.model.set('item.ordered', e.model.item.ordered+1);
}
}
customElements.define(XCustom.is, XCustom);
</script>
</dom-module>
model
はTemplateInstance
のインスタンスであり、Polymerのデータ関連のAPI:get
、set
、setProperties
、notifyPath
に加えて、配列変更メソッドを持っています。テンプレートのインスタンスに関連したパスを用いることで、これらAPIをmodel
の操作に利用できます。
例えば、上記のコードでは、ユーザーがピザの横にあるボタンをクリックすると、ハンドラは以下のコードを実行します。:
e.model.set('item.ordered', e.model.item.ordered+1);
これによって、item
の(この場合はピザの)注文数を増やします。
model
オブジェクトでは、バインドされたデータのみ利用可能です。dom-repeat
内部で、実際にバインドされたプロパティだけがmodel
オブジェクトに追加されます。そのため場合によっては、イベントハンドラからプロパティへアクセスが必要な場合、テンプレート内のプロパティにバインドする必要があるかもしれません。例えば、ハンドラがproductId
プロパティにアクセスする必要がある場合、単にそのプロパティを表示に影響を与えないプロパティにバインドします。
<template is="dom-repeat" items="{{products}}" as="product">
<div product-id="[[product.productId]]">[[product.name]]</div>
</template>
dom-repeat
テンプレートの外側におけるイベント処理
(
addEventListener
を使って)命令的に登録されたリスナーや、特定のdom-repeat
テンプレートの親ノードに設定されたリスナーに対して、model
プロパティが付加されることはありません。これらのケースでは、指定された要素から生成されたモデルデータを検索するためにdom-repeat
のmodelForElement
メソッドを利用できます。(またitemForElement
やindexForElement
に相当するメソッドも存在します。)
リストのフィルタリングとソーティング
表示されたリストのアイテムをフィルタリングまたはソートをするには、dom-repeat
にfilter
またはsort
(あるいはその両方)プロパティを指定します:
-
filter
:単一の引数(アイテム)をとるfilter
コールバック関数を指定します。関数からの返り値がtrue
ならアイテムを表示して、false
なら省略します。これは標準のArray
のfilterAPIに似ていますが、コールバックは引数に一つの配列アイテムしか取らない点に注意してください。パフォーマンス上の理由から、引数index
は含まれません。詳細については、配列インデックスのフィルタリングを参照してください。 -
sort
:標準のArray
のsortAPIに準じて比較関数を指定します。
いずれの場合もその値は、関数オブジェクトでも、ホスト要素上で定義された関数を指示する文字列でも構いません。
デフォルトでは、filter
及びsort
関数は、次のいずれかが発生した時だけ実行されます。
- 配列に[監視可能な変化](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#observable-changes)が生じた。(例えば、アイテムの追加または削除によって) -
filter
またはsort
関数が変更された。
関連のないデータの一部が変更された時に、filter
やsort
を再実行するにはrenderを呼び出してください。例えば、要素にsort
関数の動作を変更するsortOrder
プロパティがある場合、sortOrder
に変更があったときにrender呼び出すことができます。
items
の特定のサブフィールドに変更があった時に、filter
またはsort
関数を再実行するには、サブフィールドitem
のスペース区切りのリストにobserve
プロパティを設定します。そうすることで、再度フィルタリングやそーとが行われるでしょう。
例えば、dom-repeat
で次のようなフィルター処理を行なったとします。:
isEngineer: function(item) {
return item.type == 'engineer' || item.manager.type == 'engineer';
}
この時、observe
プロパティは次のように設定する必要があります。
<template is="dom-repeat" items="{{employees}}"
filter="isEngineer" observe="type manager.type">
manager.type
フィールドを変更すると、リストが再ソートされるはずです:
this.set('employees.0.manager.type', 'engineer');
ソートとフィルターの動的な変更
observe
プロパティを使って、指定したアイテムのサブプロパティをフィルタリングやソートのために監視できます。しかし、場合によっては、他の関係を持たない値に基づきフィルタやソートを動的に変更したいことがあるかもしれません。このような場合には、算出バインディングを使用し、依存関係にあるプロパティが(一つ以上)変更された時に、動的にフィルタまたはソート関数を返すことができます。
<dom-module id="x-custom">
<template>
<input value="{{searchString::input}}">
<!-- computeFilter returns a new filter function whenever searchString changes -->
<template is="dom-repeat" items="{{employees}}" as="employee"
filter="{{computeFilter(searchString)}}">
<div>{{employee.lastname}}, {{employee.firstname}}</div>
</template>
</template>
<script>
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
employees: {
type: Array,
value() {
return [
{ firstname: "Jack", lastname: "Aubrey" },
{ firstname: "Anne", lastname: "Elliot" },
{ firstname: "Stephen", lastname: "Maturin" },
{ firstname: "Emma", lastname: "Woodhouse" }
]
}
}
}
}
computeFilter(string) {
if (!string) {
// set filter to null to disable filtering
return null;
} else {
// return a filter function for the current search string
string = string.toLowerCase();
return function(employee) {
var first = employee.firstname.toLowerCase();
var last = employee.lastname.toLowerCase();
return (first.indexOf(string) != -1 ||
last.indexOf(string) != -1);
};
}
}
}
customElements.define(XCustom.is, XCustom);
</script>
</dom-module>
この例では、searchString
プロパティの値が変更されるたびcomputeFilter
が呼び出され、filter
プロパティの新しい値を算出します。
配列インデックスによるフィルタリング
Polymer内部における配列の記録(track)方法のために、配列のインデックスはフィルタ関数に渡されません。配列インデックスでアイテムを参照する際の計算量はO(n)です。これをフィルター関数上で実行ことを考えるとパフォーマンスにとても大きな影響が想定されます。
配列インデックスを参照する必要があり、パフォーマンス上の負荷を許容できる場合、次のようなコードを使用できます。:
filter: function(item) {
var index = this.items.indexOf(item);
...
}
フィルター関数はdom-repeat
をthis
の値として呼び出されるので、this.items
で元の配列にアクセスして、それをインデックスの参照に使用することができます。
この参照は、元の配列のインデックスを返します。このインデックスは、表示された(フィルター・ソートされた)配列のインデックスと一致しない可能性があります。
dom-repeatテンプレートのネスト
複数のdom-repeat
テンプレートをネストした際、親のスコープからデータにアクセスしたいかもしれません。 dom-repeat
の内部では、現在のスコープ内のプロパティによって隠蔽されない限り、親のスコープで利用可能なすべてのプロパティにアクセスできます。
例えば、dom-repeat
によって追加されたデフォルト値のitem
とindex
プロパティは、親のスコープにある同名のプロパティを覆い隠します。
ネストされたdom-repeat
テンプレートからプロパティにアクセスするには、as
属性を使用してitem
のプロパティに別の名前を割り当てます。index
プロパティに別の名前を割り当てるには、index-as
属性を使用します。
<div> Employee list: </div>
<template is="dom-repeat" items="{{employees}}" as="employee">
<div>First name: <span>{{employee.first}}</span></div>
<div>Last name: <span>{{employee.last}}</span></div>
<div>Direct reports:</div>
<template is="dom-repeat" items="{{employee.reports}}" as="report" index-as="report_no">
<div><span>{{report_no}}</span>.
<span>{{report.first}}</span> <span>{{report.last}}</span>
</div>
</template>
</template>
同期レンダリングを強制
renderを呼び出すことで、データへのどんな変更に対してもdom-repeat
テンプレートのレンダリングが同期的に行われるよう強制します。通常、変更はバッチ処理で非同期にレンダリングされます。同期的レンダリングにはパフォーマンス上の負荷があるものの、いくつかのシナリオでは役立つでしょう。:
- ユニットテストにおいて、生成されたDOMをチェックする前にアイテムがレンダリングされていることを保証する。
- 特定のアイテムへスクロールする前に、アイテムのリストがレンダリングされていることを保証する。
- データの一部が配列の外部で変更されたとき(例えば、ソート順序やフィルタ条件など)、
sort
やfilter
関数を再実行する。
render
は、Polymerの[配列の変更メソッド](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/work-with-object-and-array-data.md#mutate-an-array)によって発生するような[監視可能な変化](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#observable-changes)だけ検出します。
テンプレートが監視不能な変更を検出するようにするには、テンプレートを強制的に更新するを参照してください 。
テンプレートを強制的に更新
開発者やサードパーティーライブラリが、Polymerのメソッドを使用せず配列を変更する場合、次のいずれかを実行できます。:
-
配列の変更箇所を正確に把握している場合は、notifySplicesを使用することで、配列を監視するすべての要素に適切に通知されるようにします。
-
配列のクローンを作成します。
// Set items to a shallow clone of itself this.items = this.items.slice();
データ構造が複雑な場合、深いクローン(deep clone)が必要になることがあります。
-
変更箇所を正確に把握していない場合は、
dom-repeat
上でmutableDataプロパティを設定して、配列へのダーティチェックを無効にできます。<template is="dom-repeat" items={{items}} mutable-data> ... </template>
mutableData
セットを使用して、配列上でnotifyPath
を呼び出すと配列全体が再評価されます。// this.notifyPath('items');
詳細については、[MutableDataミックスインの使用](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/data-system-concepts.md#using-the-mutabledata-mixin)を参照してください。
配列やPolymerデータシステムとの連携に関する詳細は、[配列との連携](https://github.com/jtakiguchi/polymer-docs-japanese-translation
/blob/master/docs/polymer2/data-system/work-with-object-and-array-data.md#work-with-arrays)を参照してください。
大規模リストにおけるパフォーマンス向上
デフォルトでは、dom-repeat
は、一度にすべてのアイテムリストをレンダリングしようとします。非常に大きなアイテムリストのレンダリングにdom-repeat
使用しようとすると、レンダリングの最中UIがフリーズするかもしれません。この問題に直面した場合は、initialCountを設定して「チャンクされた(chunked)」レンダリングを有効にします。チャンクモードでは、 dom-repeat
は最初にinitialCount
で指定されたアイテムをレンダリングし、残りのアイテムはアニメーションフレーム単位で、チャンクを順番にレンダリングしていきます。これにより、UIスレッドはチャンクの間であってもユーザー入力を処理することができます。renderedItemCountプロパティ(読み取り専用)を使って、すでにレンダリングされたアイテム数を追跡することもできます。
dom-repeat
は、各チャンクでレンダリングされるアイテムの数を調整することで、ターゲットのフレームレートを維持します。またtargetFramerateの設定によってレンダリングを調整することもできます。
さらにdelayプロパティを設定することで、filter
やsort
関数が再実行される前に、一定の経過時間(デバウンス時間)を確保することもできます。
配列の選択のデータバインド(array-selector)
構造化されたデータを同期するには、バインドされたデータのパスの関係をPolymerが把握していなければいけません。array-selector
要素は、配列内から特定のアイテムが選択された際にパスの結合を保証してくれます。
items
プロパティは、ユーザーデータの配列をアプリケーションの他の部分に結合されているかもしれないselected
プロパティを更新するためにselect(item)
やdeselect(item)
を呼び出します。selected
のアイテム(群)のサブフィールドへの変更は、配列items
内のアイテムと同期的に保たれます。
配列セレクタ(array selector)は、一つまたは複数の選択をサポートします。multi
がfalse
の場合、selected
プロパティは最後に選択したアイテムを表します。 multi
がtrue
の場合、selected
プロパティは選択されたアイテム群の配列になります。
配列セレクタは、後方互換性を確保するためにレガシー(polymer.html
)インポートに含まれています。 polymer.html
をインポートしない場合は、以下のコードに示すようにarray-selector.html
をインポートしてください。
<link rel="import" href="components/polymer/polymer-element.html">
<! -- import template repeater -->
<link rel="import" href="components/polymer/src/elements/dom-repeat.html">
<!-- import array selector -->
<link rel="import" href="components/polymer/src/elements/array-selector.html">
<dom-module id="x-custom">
<template>
<div> Employee list: </div>
<template is="dom-repeat" id="employeeList" items="{{employees}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
<button on-click="toggleSelection">Select</button>
</template>
<array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></array-selector>
<div> Selected employees: </div>
<template is="dom-repeat" items="{{selected}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
</template>
</template>
<script>
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
employees: {
type: Array,
value() {
return [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'},
// ...
];
}
}
}
}
toggleSelection(e) {
var item = this.$.employeeList.itemForElement(e.target);
this.$.selector.select(item);
}
}
customElements.define(XCustom.is, XCustom);
</script>
</dom-module>
条件付きテンプレート(dom-if)
要素は、ブーリアンプロパティに基づいて条件付きでスタンプすることができます。これを実現するには、dom-if
と呼ばれる独自のHTMLTemplateElement
型の拡張を使って要素をラップします。dom-if
テンプレートは、そのif
プロパティがtrue
になった時だけそのコンテンツをDOM内にスタンプします。
if
プロパティが再度false
になった場合、デフォルトでは、スタンプされたすべての要素は非表示になります(ただし、DOMツリーには残ります)。この仕組みによって、if
プロパティが再びtrue
になった際、より高速なパフォーマンスを実現します。この動作を無効にするには、restamp
プロパティをtrue
に設定します。この場合には、要素は毎回破棄され再スタンプされるので、if
による切り替え動作は遅くなります。
条件付きテンプレートを使用する方法は二つあります。:
-
**Polymer要素または他のPolymerの管理するテンプレート内では、**省略記法
<template is="dom-repeat">
を使用してください。<template is="dom-if" if="{{condition}}"> ... </template>
-
Polymerの管理するテンプレートの外側では、ラッパー要素
<dom-if>
を使用します。<dom-if> <template> ... </template> </dom-if>
このフォームでは、通常、
items
プロパティは命令的に設定します。:var conditional = document.querySelector('dom-if'); conditional.if = true;
Polymerが管理するテンプレートには、Polymer要素のテンプレートや、dom-bind
、dom-if
、dom-repeat
に属するテンプレート、あるいはTemplatizer
によって管理されるテンプレートが含まれます。
ほとんどのケースにおいて、dom-repeat
には、一番目(省略形)のフォームを使用することになるでしょう。
テンプレートリピーターは後方互換性を確保するため、レガシーなインポート(polymer.html
)によって取り込まれます。もしpolymer.html
をインポートしない場合は、次のコードに示すようarray-selector.html
をインポートして下さい。
以下は、条件付きテンプレートがどのように動作するのかを示す簡単な例です。条件付きテンプレートの推奨された利用法は後述のガイダンスを参照してください。
例:
<link rel="import" href="components/polymer/polymer-element.html">
<! -- import conditional template -->
<link rel="import" href="components/polymer/src/elements/dom-if.html">
<dom-module id="x-custom">
<template>
<!-- All users will see this -->
<my-user-profile user="{{user}}"></my-user-profile>
<template is="dom-if" if="{{user.isAdmin}}">
<!-- Only admins will see this. -->
<my-admin-panel user="{{user}}"></my-admin-panel>
</template>
</template>
<script>
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
user: Object
}
}
}
customElements.define(XCustom.is, XCustom);
</script>
</dom-module>
条件付きテンプレートを使用すると多少のオーバーヘッドが発生するため、CSSを使用することで容易に表示/非表示にできるような小さなUI要素には使用すべきでありません。
代わりに、読み込み時間を改善させたり、ページのメモリ容量を減らすために条件付きテンプレートを使って下さい。例えば:
-
ページ中のセクションをレイジーロードする。最初の描画時に必要のないページ中の一部要素は、
dom-if
を使用してその定義が読み込みを終えるまで非表示にすることができます。この条件付きテンプレートの利用法に関しては、ケーススタディ:ショップアプリで説明しています。 -
大規模サイトや複雑なサイトにおいてメモリの使用量を削減します。複雑なビューを複数持つシングルページアプリケーション(SPA)では、
restamp
プロパティが設定されたdom-if
の中に各ビューを置くのは有効かもしれません。これにより、ユーザーが表示を切り替える(その箇所のDOMを再生成する)たびに、ある程度のレイテンシは犠牲になりますが、メモリの利用効率が改善されます。
条件付きテンプレートをどんな場面で利用するかについて、どんな場合にも当てはまる画一的な指針はありません。サイトのプロファイリングは、条件付きテンプレートの効果的な使い所を把握するために役立つでしょう。
自動バインディングテンプレート(dom-bind)
Polymerのデータバインディングは、Polymerによって管理されるテンプレート内だけで使用できます。したがって、データバインディングは、要素のDOMテンプレート内(あるいはdom-repeat
やdom-if
テンプレート内)では動作しますが、メインドキュメントに配置された要素では機能しません。
新たにカスタム要素を定義することなくPolymerのバインディングを利用するには、<dom-bind>
要素を使用します。このテンプレートは、その子のテンプレート情報の内容をメインドキュメントに即座にスタンプします。自動バインディングテンプレートによるデータバインディングは、バインディングスコープとして<dom-bind>
要素そのものを利用します。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/src/elements/dom-bind.html">
<link rel="import" href="polymer/src/elements/dom-repeat.html">
</head>
<body>
<!-- Wrap elements with auto-binding template to -->
<!-- allow use of Polymer bindings in main document -->
<dom-bind>
<template>
<template is="dom-repeat" items="{{data}}">
<div>{{item.name}}: {{item.price}}</div>
</template>
</template>
</dom-bind>
<script>
var autobind = document.querySelector('dom-bind');
// The dom-change event signifies when the template has stamped its DOM.
autobind.addEventListener('dom-change', function() {
console.log('template is ready.')
});
// set data property on dom-bind
autobind.data = [
{ name: 'book', price: '$5.00'},
{ name: 'pencil', price: '$1.00'},
{ name: 'flux capacitor', price: '$8,000,000.00'}
];
</script>
</body>
</html>
dom-bind
の全ての機能は、Polymer要素の中であればすでに使用できます。自動バインディングテンプレートは、Polymer要素の外部のみで利用すべきです。
同期的レンダリングの強制:
dom-repeat
と同様、dom-bind
は、render
メソッドとmutableData
プロパティを提供しています。(同期レンダリングを強制とテンプレートを更新で説明した通りです。)
dom-changeイベント
あるテンプレートのヘルパー要素がDOMツリーを更新すると、dom-change
イベントが発生します。
多くのケースでは、生成したノードと直接やりとりするのではなく、モデルデータの変更によって生成したDOMとやりとりするべきです。ノードに直接アクセスする必要がある場合には、dom-change
イベントを使用することができます。