Help us understand the problem. What is going on with this article?

Polymerドキュメント(日本語) Custom elements/Declare properties 〜プロパティの宣言〜

More than 3 years have passed since last update.

目次へ移動

翻訳ドキュメントの管理ページ

デフォルト値を追加したりデータシステムの様々な機能を利用するために、要素にプロパティを宣言することができます。

宣言したプロパティには以下のような項目を指定できます:

  • プロパティの型(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 型:コンストラクタ(BooleanDateNumberStringArrayObjectいずれか)

指定された型は、属性からプロパティにデシリアライズに使用されます。0.5系と違い、プロパティの型はコンストラクタの型によって明示的に指定されます。詳細は属性のデシリアライズを参照してください 。
value 型:booleanまたはnumberstringfunction

プロパティのデフォルト値となります。もし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(コンストラクタによってObjectStringなどに指定された型)以外が記述されていない場合(訳注:”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またはNumbertoStringを使用してシリアライズされます。
  • Boolean:値を持たない属性が設定(trueの場合)または、削除(falseの場合)されます。
  • ArrayまたはObjectJSON.stringifyを使用してシリアライズされます。

カスタム要素に独自のシリアライズ処理を実装したい場合には、要素のserializeメソッドをオーバーライドして下さい。

暗黙的に宣言されたプロパティ

データバインディングにプロパティを追加したり、オブザーバー、算出プロパティ、算出バインディングといった機能により、依存関係をもつプロパティを追加した場合には、プロパティが暗黙的に宣言されたことになります。

Polymerはこれら暗黙的に宣言されたプロパティに自動的にsetterメソッドを作成します。しかし、暗黙的に宣言されたプロパティをマークアップから作成することはできません。

非公開および保護されたプロパティ

JavaScriptにはプロパティを真に保護する機能はありません。Polymer要素では、慣例に従い命名規約を通じてこれらを表現します。保護されるべきプロパティやメソッドはシングルアンダースコア(_protectedProp)で明示します。(サブクラスで利用または上書きされることは許可されますが、publicな利用は意図しません)また、クラスのprivateなメンバーであることを明示するにはダブルアンダースコア(__privateProp)を利用します。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away