Polymer 1.0 Global Variables

Gro*_*kys 31 javascript html5 polymer polymer-1.0

在Polymer 0.5中,关于全局变量的建议如本问题/答案中所述:

聚合物全局变量

但是在Polymer 1.0中,这似乎不起作用.更改通知不会在基础模型上自动生成,<dom-module>而是在相反的情况下生成,这意味着将仅在其中一个上生成更改通知<app-globals>.

在Polymer 1.0中实现此模式的推荐方法是什么?

Arc*_*rco 12

聚合物元素<iron-meta>也是一种选择.对我来说这是最简单的解决方案.


小智 11

我已经将Etherealones的解决方案扩展为一个行为,并扩展了Polymers"set"和"notifyPath"方法以自动触发更新.这与我可以跨组件/元素进行真正的数据绑定一样接近:

全局-behavior.html:

<script>
var instances = [];
var dataGlobal = {};

var GlobalsBehaviour = {

  properties: {
    globals: {
      type: Object,
      notify: true,
      value: dataGlobal
    }
  },

  ready: function() {
    var _setOrig = this.set;
    var _notifyPathOrig = this.notifyPath;
    this.set = function() {
      _setOrig.apply(this, arguments);
      if (arguments[0].split(".")[0] === "globals") {
        this.invokeInstances(_notifyPathOrig, arguments);
      }
    };
    this.notifyPath = function(path, value) {
      _notifyPathOrig.apply(this, arguments);
      if (arguments[0].split(".")[0] === "globals") {
        this.invokeInstances(_notifyPathOrig, arguments);
      }
    };
  },

  invokeInstances: function(fn, args) {
    var i;
    for (i = 0; i < instances.length; i++) {
      instance = instances[i];
      if (instance !== this) {
        fn.apply(instance, args);
      }
    }
  },

  attached: function() {
    instances.push(this);
  },

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

</script>
Run Code Online (Sandbox Code Playgroud)

在所有应该有权访问全局变量的聚合物元素中:

  <script>
    Polymer({
      is: 'globals-enabled-element',
      behaviors: [GlobalsBehaviour]
    });
  </script>
Run Code Online (Sandbox Code Playgroud)

例子:

  1. 在Github上发布了一个完整的例子作为Gist
  2. 这是一个片段,可以看到它的实际效果:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Globals Behavior Example</title>
        <link rel="import" href="//rawgit.com/Polymer/polymer/master/polymer.html">
        <dom-module id="globals-enabled-element">
          <template>
            <input type="text" value="{{globals.my_variable::input}}">
          </template>
          <script>
            var instances = [];
            var dataGlobal = {};
            
            var GlobalsBehaviour = {
              
              properties: {
                globals: {
                  type: Object,
                  notify: true,
                  value: dataGlobal
                }
              },
              
              ready: function() {
                var _setOrig = this.set;
                var _notifyPathOrig = this.notifyPath;
                this.set = function() {
                  _setOrig.apply(this, arguments);
                  if (arguments[0].split(".")[0] === "globals") {
                    this.invokeInstances(_notifyPathOrig, arguments);
                  }
                };
                this.notifyPath = function(path, value) {
                  _notifyPathOrig.apply(this, arguments);
                  if (arguments[0].split(".")[0] === "globals") {
                    this.invokeInstances(_notifyPathOrig, arguments);
                  }
                };
              },
              
              invokeInstances: function(fn, args) {
                var i;
                for (i = 0; i < instances.length; i++) {
                  instance = instances[i];
                  if (instance !== this) {
                    fn.apply(instance, args);
                  }
                }
              },
              
              attached: function() {
                instances.push(this);
              },
              
              detached: function() {
                var i;
                i = instances.indexOf(this);
                if (i >= 0) {
                  instances.splice(i, 1);
                }
              }
            };
          </script>
          <script>
            Polymer({
              is: 'globals-enabled-element',
              behaviors: [GlobalsBehaviour]
            });
          </script>
        </dom-module>
      </head>
      <body>
        <template is="dom-bind">
          <p>This is our first polymer element:</p>
          <globals-enabled-element id="element1"></globals-enabled-element>
          <p>And this is another one:</p>
          <globals-enabled-element id="element2"></globals-enabled-element>
        </template>
      </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

  • 另外,我宁愿自己为元素提供全局变量,也许你应该期望变量名`_globals`并在`Behavior.ready`中使用`console.warn`(如果它不存在).单个_global_全局听起来不太好. (2认同)

Eth*_*one 4

iron-signals为此,我已经实现了类似用途的模式。所以基本原则是当更新发生时你手动通知其他实例。

考虑一下:

<dom-module id="x-global">
<script>
(function() {
  var instances = [];

  var dataGlobal = {};

  Polymer({
    is: 'x-global',

    properties: {
      data: {
        type: Object,
        value: dataGlobal,
      },
    },

    attached: function() {
      instances.push(this);
    },

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

    set_: function(path, value) {
      this.set(path, value);

      instances.forEach(function(instance) {
        if (instance !== this) { // if it is not this one
          instance.notifyPath(path, value);
        }
      }.bind(this));
    },

    notifyPath_: function(path, value) {
      instances.forEach(function(instance) {
        instance.notifyPath(path, value);
      });
    },

    fire_: function(name, d) {
      instances.forEach(function(instance) {
        instance.fire(name, d);
      });
    },
  });
})();
</script>
</dom-module>
Run Code Online (Sandbox Code Playgroud)

您将简单地调用具有下划线后缀的版本,就像fire_触发事件时一样。我猜你甚至可以用这种模式创建某种聚合物行为。

请注意,前面的下划线属性已被 Polymer 使用,因此不要继续将它们转换为_fire.

PS:我没有四处寻找解决如何反映通知的问题,this.push(array, value);因为我不需要它。我不知道这样是否可以。应该去找Polymer.Base.push