Polymer 1.0 Global Variables

2019-01-11 00:44发布

In Polymer 0.5 the advice on globals was as outlined in this question/answer:

Polymer global variables

However in Polymer 1.0 this doesn't seem to work. Change notifications are not automatically generated on the underlying model, they are generated on the <dom-module> instead which means that change notifications will be generated on only one of the <app-globals>.

What is the recommended way of implementing this pattern in Polymer 1.0?

8条回答
相关推荐>>
2楼-- · 2019-01-11 01:26

I have tried to improve on Alexei Volkov's answer, but I wanted to define the global variables separately. Instead of the getters/setters I used the observer property and saved the key together with the instances.

The usage is:

<app-data  key="fName" data="{{firstName}}" ></app-data>

whereas the keyproperty defines the name of the global variable.

So for example you can use:

<!-- Output element -->
<dom-module id="output-element" >
  <template>
    <app-data key="fName" data="{{data1}}" ></app-data>
    <app-data key="lName" data="{{data2}}" ></app-data>
    <h4>Output-Element</h4>
    <div>First Name: <span>{{data1}}</span></div>
    <div>Last Name: <span>{{data2}}</span></div>
  </template>
</dom-module>

<script>Polymer({is:'output-element'});</script>

Definition of the <app-data>dom module:

<dom-module id="app-data"></dom-module>
<script>
(function () {
    var instances = [];
    var vars = Object.create(Polymer.Base);

    Polymer({
        is: 'app-data',
        properties: {
           data: {
                type: Object,
                value: '',
                notify: true,
                readonly: false,
                observer: '_data_changed'
            },
          key: String
        },
        created: function () {
          key = this.getAttribute('key');
          if (!key){
            console.log(this);
            throw('app-data element requires key');
          }

          instances.push({key:key, instance:this});
        },

        detached: function () {
            key = this.getAttribute('key');
            var i = instances.indexOf({key:key, instance:this});
            if (i >= 0) {
                instances.splice(i, 1);
            }
        },

      _data_changed: function (newvalue, oldvalue) {
        key = this.getAttribute('key');
        if (!key){
            throw('_data_changed: app-data element requires key');
            }
        vars.set(key, newvalue);

        // notify the instances with the correct key
        for (var i = 0; i < instances.length; i++) 
        {
          if(instances[i].key == key)
          {
            instances[i].instance.notifyPath('data', newvalue);
          }
        }
      }


    });
})();
</script>

Fully working demo is here: http://jsbin.com/femaceyusa/1/edit?html,output

查看更多
爷、活的狠高调
3楼-- · 2019-01-11 01:35

Using ootwch's solution, I ran into a race condition situation with lazy-loaded components.

As posted, lazy-loaded components are not initialized with the value from the shared data.

In case anyone else runs into the same problem, I think I fixed it by adding a ready callback like this:

ready: function() {
  const key = this.getAttribute('key')
  if (!key) {
    throw new Error('cm-app-global element requires key')
  }

  const val = vars.get(key)
  if (!!val) {
    this.set('data', val)
  }
},

Hope this saves someone some pain.

查看更多
登录 后发表回答