1

カスタム ポリマー要素の次の使用法を検討してください。

<app-header bar-foo="[[abc.def.ghi]]" app-title="[[appTitle]]"></app-header>

ここでは、カスタム要素に 2 つの変数をバインドしますapp-header。ここで、値を更新したい場合は、次のようにすると思います ( app-header! の親で)。

this.abc.def.ghi = 10;
this.appTitle = 'New title';

ただし、これはappTitlenotのみを更新しますabc.def.ghi。この値も更新するには、次のようにする必要があります。

this.abc = {def: {ghi: 10}};

これがなぜなのかわかる方いたら教えてください!!

とにかく、せっかくだから使ってみたいImmutable!ただし、これにより、データがカスタム要素にバインドされる方法にいくつかの問題が発生します

スニペットの例を次に示します。

<dom-module id="my-app">
    <template>
        <app-header hits="[[state.get('page').get('hits')]]"></app-header>
    </template>
    <script>
        (function () {
            class MyApp {
                beforeRegister() {
                    this.is = 'my-app';

                    this.properties = {
                        state: {
                            type: Object,
                            notify: true,
                            value: Immutable.Map({
                                page: Immutable.Map({hits: 10})
                            })
                        }
                    };
                }
            }

            Polymer(MyApp);
        })();
    </script>
</dom-module>

したがって、データを要素にバインドするときに問題が発生します。

<app-header hits="[[state.get('page').get('hits')]]"></app-header>

このようなことは可能ですか、それとも何か他のことを完全に間違っていますか?

4

2 に答える 2

1

構造データを更新するときは、Polymer API を使用する必要があります。これにより、変更されたイベントがトリガーされ、バインドされたデータが更新されます。パス変更通知に関するこの記事をご覧ください。この場合、コードを次のように変更する必要があります。

this.set('abc.def.ghi', 10);

Immutable については詳しくありませんが、この種の式は Polymer ではサポートされていません。

hits="[[state.get('page').get('hits')]]"

要素または計算関数の (サブ) プロパティにバインドできます。計算関数は、要素で定義する必要があります。データ バインディングでは、任意のオブジェクトに対して任意の関数を呼び出すことはできません。おそらく、setAPI を使用すると、Immutable を使用する必要がなくなります。

于 2015-10-20T13:00:07.677 に答える
1

この投稿が少し古いことは承知していますが、Immutable JS と Polymer を一緒に使用することを検討したかったので、答えたいと思いました。理由は次のとおりです。

  1. 私のチームはポリマーを使用してアプリケーションを構築していますが、それを変更することはできません
  2. 不変は元に戻すとやり直しの実装を簡単にし、それは要件です

不変のjsオブジェクトをポリマーにバインドする方法を見つけましたが、見苦しくハッキーであることを警告してください。


不変オブジェクトへのバインディング

ポリマーが不変の js プロパティにアクセスできるようにするには、エレメント プロトタイプにタイプのプロパティを作成する必要があります。これObjectは、不変の js とポリマーの間の一種の「アダプター」として機能します。

ポリマー API が の形式でオブジェクトにアクセスできるように、このオブジェクト プロパティは JavaScriptゲッター(または) を使用する必要がありますが、実際の実装では不変オブジェクトにアクセスします。Object.definePropertyobject.property

let immutableMap = Immutable.map({count: 0, text: 'world'});

Polymer({
  // ...
  properties: {
    /**
     * This property is an 'adapter' to assign a property path to access the immutablejs object.
     * The property starts with an underscore because we don't want the user to set it
     */
    _adapter: {
      type: Object,
      value: {
        /**
         * the properties of this object use
         * [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
         * so that polyer can access the object like `obj.count`
         */
        get count() { return immutableMap.get('count'); },
        get text() { return immutableMap.get('text'); }
      }
    }
  }
  // ...
});

上記の例では、 と の 2 つのメソッドを持つ type のプロパティを作成しましObjectた。これらのメソッドは先頭に が付加されているため、メソッド名だけでアクセスできると想定されています。これはgetterです。counttextget

これを行うと、ポリマーがオブジェクトにバインドできるようになり_adapter、そのオブジェクトは から値を「取得」しますimmutableMap

不変オブジェクトの変更

これを機能させるために必要な 2 番目の要素は、不変オブジェクトを変更することです。オブジェクトは不変であるため、双方向バインディングはオプションではありません。不変を使用する場合、不変オブジェクトを再割り当てして再レンダリングするイベント リスナーを追加する必要があります。

そのためには、 Polymer のダーティ チェックをオーバーライドする必要があります。使用notifyPathしてみましたが、例外として機能しないことがわかりました。 notifyPath動作するはずです。

警告

ダーティ チェックをオーバーライドしていて、仮想 DOM ライブラリ (react など) を使用していないため、不変オブジェクトを使用する_adapterには、不変オブジェクトで変更が発生するたびに を使用する要素を再レンダリングする必要があります。これは、使用することで改善できますnotifyPath

完全なデモ (取り消しあり)

これは、不変の js と Polymer を組み合わせた完全なデモです。不変を使用する少しのインセンティブのために元に戻す機能を追加しました-不変のJSは元に戻すとやり直すを非常に簡単にします:D

<base href="https://cdn.rawgit.com/download/polymer-cdn/1.7.0/lib/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.min.js"></script>

<!-- Defines element markup -->
<dom-module id="hello-world">
  <template>
    <div>
      <!--use only one-way binding because the object is immutable-->
      <button on-tap="onButtonClick">clicks <span>[[_adapter.count]]</span></button>
    </div>
    <div>
      <input on-input="onInput" type="text" value="[[_adapter.text]]">
      <h1>hello, <span>[[_adapter.text]]</span>!</h1>
    </div>
    <div>
      <button on-tap="onUndo">Undo</button>
    </div>
  </template>

  <!-- Registers custom element -->
  <script>
    // immutable map is defined out of the scope of the polymer object
    let immutableMap = Immutable.Map({
      count: 0,
      text: 'world'
    });
    // add undos
    let undos = [];

    Polymer({
      is: 'hello-world',
      /**
       * every event should reassign the `immutableMap` then manually `notifyPath`
       */
      onButtonClick: function () {
        undos.push(immutableMap);
        immutableMap = immutableMap.update('count', count => count + 1);
        this.notifyPath('_adapter.count');
      },
      onInput: function (event) {
        undos.push(immutableMap);
        immutableMap = immutableMap.set('text', event.target.value);
        this.notifyPath('_adapter.text');
      },
      onUndo: function () {
        if (undos.length) {
          immutableMap = undos.pop();
        }
        const obj = this._adapter;
        this._adapter = {};
        this._adapter = obj;
      },
      properties: {
        /**
         * This property is an 'adapter' to assign a property path to access the immutablejs object.
         * The property starts with an underscore because we don't want the user to set it
         */
        _adapter: {
          type: Object,
          value: {
            /**
             * the properties of this object use
             * [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
             * so that polymer can access the object like `obj.count`
             */
            get count() { return immutableMap.get('count'); },
            get text() { return immutableMap.get('text'); }
          }
        }
      }
    });
  </script>
</dom-module>

<hello-world></hello-world>

于 2017-05-15T18:36:46.823 に答える