デフォルト値を追加したりデータシステムの様々な機能を利用するために、要素にプロパティを宣言することができます。
宣言したプロパティには以下のような項目を指定できます:
- プロパティの型(type)
- デフォルト値
- プロパティの変更を監視するオブザーバー。プロパティ値が変更される度に特定のメソッドを呼び出します。
- 読み取り専用(read-only)ステータス。プロパティ値の予期せぬ変更を防ぎます。
- 双方向データバインディングのサポート。プロパティ値が変更されるたびにイベントを発生させます。
- 算出プロパティ(computed property)。他のプロパティを元に値を動的に計算します。
- 属性へのプロパティの反映を指定。プロパティ値がアップデートされたときに対応する属性の値を変更します。
これらの機能の多くは、データシステムに緊密に統合されており、それらはデータシステムのセクションに解説があります。
さらに、宣言的プロパティは、マークアップから属性を使って設定することもできます(詳細については、属性のデシリアライズのセクションを参照してください)。
ほとんどの場合、要素のパブリックAPIの一部となるプロパティはproperties
オブジェクト内で宣言する必要があります。
プロパティを宣言するには、要素のクラスに静的getterメソッドproperties
を追加します。getterメソッドは、プロパティの宣言を含むオブジェクトを返す必要があります。
例:
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
user: String,
isHappy: Boolean,
count: {
type: Number,
readOnly: true,
notify: true
}
}
}
}
customElements.define(XCustom.is, XCustom);
このproperties
オブジェクトは、各プロパティに以下のキーを提供しています。
キー | 詳細 |
---|---|
type |
型:コンストラクタ(Boolean 、Date 、Number 、String 、Array 、Object いずれか)指定された型は、属性からプロパティにデシリアライズに使用されます。0.5系と違い、プロパティの型はコンストラクタの型によって明示的に指定されます。詳細は属性のデシリアライズを参照してください 。 |
value |
型:boolean またはnumber 、string 、function プロパティのデフォルト値となります。もし value が関数の場合、関数が呼び出され、戻り値がプロパティのデフォルト値に使用されます。デフォルト値がインスタンスに固有な配列またはオブジェクトでなければならない場合は、関数内で配列またはオブジェクトを作成します。詳細については、デフォルトのプロパティ値の設定を参照してください 。 |
reflectToAttribute |
型: boolean true を指定すると、プロパティ値が変更された場合、対応する属性がホストノードに設定されるようになります。プロパティ値がブール値の場合には、属性は標準のHTML属性のブール値として作成されます(trueの場合に記述され、falseの場合には記述されない)。プロパティの型がそれ以外なら、属性値はプロパティ値を文字列で表現したものになります。Polymer0.5系の reflect に相当します。詳細については、属性へのプロパティの反映を参照してください。 |
readOnly |
型: boolean true を指定した場合、プロパティは代入やデータバインディングによって直接的に設定することができなくなります。詳細については、読み取り専用プロパティを参照してください。 |
notify |
型: boolean true を指定した場合、プロパティに双方向データバインディングが使用できます。さらに、プロパティが変更されるたびにproperty-name-changed イベントが発生します。詳細については、プロパティ変更通知イベント(notify) を参照してください。 |
computed |
型: string プロパティの値は、メソッド名と引数リストとして解釈されます。このメソッドは、引数の値のいずれかが変更されるたびに、プロパティ値を算出するために呼び出されます。算出プロパティは常に読み取り専用です。詳細については、算出プロパティを参照してください 。 |
observer |
型: string プロパティ値は、プロパティ値が変更された時に呼び出されるメソッドの名前として解釈されます。0.5系とは異なり、プロパティ変更ハンドラは明示的に登録する必要がある点に注意してください。 propertyNameChanged メソッドは自動的に実行されることはありません。詳細については、プロパティ変更コールバック(observers) を参照してください。 |
プロパティ名の属性名へのマッピング
データバインディング、属性からのプロパティへのデシリアライズ、およびプロパティの属性への反映において、Polymerは属性名をプロパティ名に、またその逆に、マッピングを行います。
属性名をプロパティ名にマッピングする場合:
-
属性名は小文字のプロパティ名に変換されます。例えば、属性名が
firstName
であればfirstname
にマップされます。 -
属性名にダッシュ(-)が含まれる場合には、キャメルケース(camelCase)に変換されます。つまりダッシュ(-)を削除して、ダッシュの後の各文字を大文字に変換します。例えば、属性名が
first-name
であればfirstName
にマップされます。
上記とは反対に、プロパティ名を属性名に変換する際は、同様のマッピングが逆に実行されます(例えば、プロパティにreflectToAttribute: true
が定義されている場合など)。
互換性に関する注意: 0.5系では、Polymerは属性名を一致したプロパティにマップしようとしました。例えば、もし要素上でプロパティでfooBarが定義されている場合、属性
foobar
は、プロパティfooBar
にマップされます。このようなプロパティのマッピングは、**1.0系以降の属性では発生しません。**属性からプロパティへのマッピングは、上記で示したルールに従って要素の登録のタイミングで実行されます。
属性のデシリアライズ
properties
オブジェクトでプロパティが設定されている場合、プロパティ名に一致するインスタンスの属性は、指定された型に従ってデシリアライズされ、インスタンス上の同名のプロパティに割り当てられます。
properties
オブジェクトにtype
(コンストラクタによってObject
、String
などに指定された型)以外が記述されていない場合(訳注:”property: String" のような略記のこと)、属性の値をproperties
オブジェクトのtype
プロパティの値に直接設定することができます。そうでない場合(訳注:略記でない場合)には、 properties
オブジェクト内でtype
キーの値として設定されるべきです。
型システムは、Boolean型、Number型、JSON形式で記述されたObject型やArray型、解析可能(parsable)な文字列表現として記述されたDate型をサポートします。
Boolean型プロパティは属性値の有無によって設定されます。つまり属性が存在すれば(属性の値は関係ない)プロパティにtrueが設定され、属性が存在しなければ、プロパティはデフォルト値になります。
例:
<script>
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
user: String,
manager: {
type: Boolean,
notify: true
}
}
}
attached: function() {
// render
this.textContent = 'Hello World, my user is ' + (this.user || 'nobody') + '.\n' +
'This user is ' + (this.manager ? '' : 'not') + ' a manager.';
}
}
customElements.define(XCustom.is, XCustom);
</script>
<x-custom user="Scott" manager></x-custom>
<!--
<x-custom>'s text content becomes:
Hello World, my user is Scott.
This user is a manager.
-->
属性から要素にキャメルケース(camelCase)のプロパティを設定するには、属性名としてダッシュケース(dash-case)を使用する必要があります。
例:
<script>
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
userName: String
}
}
}
customElements.define(XCustom.is, XCustom);
</script>
<x-custom user-name="Scott"></x-custom>
<!-- Sets <x-custom>.userName = 'Scott'; -->
注意:属性からプロパティへのデシリアライズは、作成時と実行時(例えば、
setAttribute
を使用して実行時に属性を変更する場合)の両方で発生します。しかし、属性は静的マークアップからプロパティを設定するためだけに使用することが推奨され、実行時にプロパティを変更するには(訳補:属性からではなく)直接的に設定するように下さい。
ブール値のプロパティの設定
マークアップからBoolean型のプロパティを指定したい場合、デフォルト値をfalse
にする必要があります。デフォルト値がtrue
場合、マークアップからfalse
を指定することはできません。なぜなら、属性の有無にかかわらず、true
と等価であると判定されるためです。これはWebプラットフォームにおける属性の標準的な振る舞いです。
この振る舞いがあなたのユースケースに合わない場合は、代わりに文字列や数値を属性の値に利用できます。
オブジェクトと配列のプロパティの設定
プロパティがオブジェクトや配列の場合、これらはJSON形式にして渡すことができます:
<my-element book='{ "title": "Persuasion", "author": "Austen" }'></my-element>
上記のように、JSONでは二重引用符が必要な点に注意してください。
デフォルトのプロパティ値の設定
properties
オブジェクトのプロパティのデフォルト値は、value
フィールドを使用することで設定できます。プロパティ値は、プリミティブな値でも、値を返す関数でも構いません。
関数を指定した場合、Polymerは要素のインスタンスごとに一度ずつ呼び出します。
オブジェクトのプロパティや配列の値を初期化する際は、関数を利用して、すべての要素のインスタンス間でオブジェクトや配列を共有せず、要素ごとに独自に値をコピーして取得するようにします。
例:
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
mode: {
type: String,
value: 'auto'
},
data: {
type: Object,
notify: true,
value: function() { return {}; }
}
}
}
}
プロパティ変更通知イベント(notify)
プロパティをnotify: true
に設定すると、プロパティ値が変更される度に、以下の名前のイベントが発火します。
property-name-changed
イベント名のproperty-name
部分は、プロパティ名をダッシュケースで表現したものです。例えば、this.firstName
が変更されるとfirst-name-changed
が発火するといった具合です。
これらのイベントは、双方向データバインディングシステムによって利用されます。外部のスクリプトからaddEventListener
を使用してイベント(first-name-changed
のような)を監視することもできます。
プロパティ変更通知とデータシステムの詳細については、データフローを参照してください。
読み取り専用プロパティ(readOnly)
プロパティがデータを生成(produce)するだけで消費(consume)しない場合、properties
の定義においてプロパティのreadOnly
フラグをtrue
に設定することで、ホストからの不測の変更を明示的に避けることができます。
実際に要素の読み取り専用プロパティの値を変更するには、慣例に従い用意された非公開のsetterメソッド_setProperty(value)
を利用すべきです。
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
response: {
type: Object,
readOnly: true,
notify: true
}
}
}
responseHandler(response) {
// set read-only property
this._setResponse(response);
}
}
読み取り専用プロパティとデータバインディングに関する詳細については、データフローの制御方法を参照してください 。
プロパティの属性への反映(reflectToAttribute)
ある特定のケースにおいては、HTMLの属性値とプロパティ値を同期させておくと便利かもしれません。properties
オブジェクト内のプロパティにreflectToAttribute: true
を設定することで実現できます。これによって、プロパティに対する監視可能な変更は、同名の属性にシリアライズされます。
class XCustom extends Polymer.Element {
static get is() {return 'x-custom'; }
static get properties() {
return {
loaded: {
type: Boolean,
reflectToAttribute: true
}
}
}
_onLoad() {
this.loaded = true;
// results in this.setAttribute('loaded', true);
}
}
属性へのシリアライズ
プロパティを属性に反映する場合や属性にプロパティをバインドする場合、プロパティの値は属性にシリアライズされます。
デフォルトでは、プロパティのtype
の値に関係なく、値の現在の型に従って以下のようにシリアライズされます。
-
String
:シリアライズは不要です。 -
Date
またはNumber
:toString
を使用してシリアライズされます。 -
Boolean
:値を持たない属性が設定(true
の場合)または、削除(false
の場合)されます。 -
Array
またはObject
:JSON.stringify
を使用してシリアライズされます。
カスタム要素に独自のシリアライズ処理を実装したい場合には、要素のserialize
メソッドをオーバーライドして下さい。
暗黙的に宣言されたプロパティ
データバインディングにプロパティを追加したり、オブザーバー、算出プロパティ、算出バインディングといった機能により、依存関係をもつプロパティを追加した場合には、プロパティが暗黙的に宣言されたことになります。
Polymerはこれら暗黙的に宣言されたプロパティに自動的にsetterメソッドを作成します。しかし、暗黙的に宣言されたプロパティをマークアップから作成することはできません。
非公開および保護されたプロパティ
JavaScriptにはプロパティを真に保護する機能はありません。Polymer要素では、慣例に従い命名規約を通じてこれらを表現します。保護されるべきプロパティやメソッドはシングルアンダースコア(_protectedProp
)で明示します。(サブクラスで利用または上書きされることは許可されますが、publicな利用は意図しません)また、クラスのprivateなメンバーであることを明示するにはダブルアンダースコア(__privateProp
)を利用します。