【问题标题】:Shared behavior state across custom elements跨自定义元素共享行为状态
【发布时间】:2015-06-10 04:04:00
【问题描述】:

我有这两个自定义聚合物元素 (Polymer 1.0.3):

  1. 显示要翻译的文本。
  2. 显示按钮以触发加载翻译。

我还有一个Behavior 保存翻译(json 对象)并包含使翻译成为可能的所有功能。

这是我期望发生的:

  1. 单击元素 2 中的按钮
  2. 翻译加载到行为中
  3. 在行为中设置语言选择
  4. 元素 1 中的文本使用翻译后的对等内容进行更新

第 1 步到第 3 步会发生,但第 4 步不会。文本永远不会更新。如果元素 1 和 2 组合为同一个元素,我可以让它工作,但如果它们是分开的(任何它们需要分开),则不能。

如果您想了解“kick”属性,这是我从 Polymer 0.5 中学到的。当这两个元素结合在一起时,它就可以工作了,所以我认为当元素分开时它是必要的。

知道如何实现这一点吗?我对替代范式持开放态度。

代码

这就是我的代码的大致布局方式。我还发了plunker with a single-page test case

index.html

<!doctype html>
<html>

<head>
  <script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
  <link rel="import" href="behavior.html">
  <link rel="import" href="element1.html">
  <link rel="import" href="element2.html">
</head>

<body>
  <my-element></my-element>
  <another-element></another-element>
</body>

</html>

元素 1

<dom-module id="my-element">
  <template>
    <p>{{localize(label, kick)}}</p>
  </template>
</dom-module>

<script>
  Polymer({
    is: 'my-element',
    behaviors: [
      behavior
    ],
    properties: {
      label: {
        type: String,
        value: 'original'
      }
    }
  });
</script>

元素 2

<dom-module id="another-element">
  <template>
    <button on-click="buttonClicked">load</button>
  </template>
</dom-module>
<script>
  Polymer({
    is: 'another-element',
    behaviors: [
      behavior
    ],
    buttonClicked: function() {
      this.registerTranslation('en', {
        original: 'changed'
      })
      this.selectLanguage('en');
    }
  });
</script>

行为

<script>
  var behavior = {
    properties: {
      kick: {
        type: Number,
        value: 0
      },
      language: {
        type: String,
        value: 'fun'
      },
      translations: {
        type: Object,
        value: function() {
          return {};
        }
      }
    },
    localize: function(key, i) {
      if (this.translations[this.language] && this.translations[this.language][key]) {
        return this.translations[this.language][key];
      }
      return key;
    },
    registerTranslation: function(translationKey, translationSet) {
      this.translations[translationKey] = translationSet;
    },
    selectLanguage: function(newLanguage) {
      this.language = newLanguage;
      this.set('kick', this.kick + 1);
    }
  };
</script>

【问题讨论】:

    标签: javascript internationalization polymer polymer-1.0


    【解决方案1】:

    首先,虽然概念是让behavior 成为实例之间共享数据的管道,但每个实例都将拥有自己的translations 对象和kick 属性的副本。

    其次,即使该数据被私有化以便可以共享,通过localize(label, kick) 进行的kick 绑定与修改kick 的表达式处于不同的范围内(即this.set('kick', this.kick + 1); [{sic} this可能只是this.kick++;])。

    要通知 N 个实例共享数据的更改,必须跟踪这些实例。一个很好的方法是附加事件侦听器。另一种方法是简单地保留一个列表。

    这是您设计的示例实现:

        <script>
          (function() {
            var instances = [];
            var translationDb = {};
            var language = '';
    
            window.behavior = {
              properties: {
                l10n: {
                  value: 0
                }  
              },
              attached: function() {
                instances.push(this);
              },
              detached: function() {
                this.arrayDelete(instances, this);
              },
              _broadcast: function() {
                instances.forEach(function(i) {
                  i.l10n++;
                });
              },
              localize: function(key, i) {
                if (translationDb[language] && translationDb[language][key]) {
                  return translationDb[language][key];
                }
                return key;
              },
              registerTranslation: function(translationKey, translationSet) {
                translationDb[translationKey] = translationSet;
              },
              selectLanguage: function(newLanguage) {
                language = newLanguage;
                this._broadcast();
              }
            };
          })();
      </script>
    
      <dom-module id="my-element">
        <template>
          <p>{{localize(label, l10n)}}</p>
        </template>
        <script>
          Polymer({
            behaviors: [
              behavior
            ],
            properties: {
              label: {
                type: String,
                value: 'original'
              }
            }
          });
        </script>
      </dom-module>
    
      <dom-module id="another-element">
        <template>
          <button on-tap="buttonClicked">load</button>
        </template>
        <script>
          Polymer({
            behaviors: [
              behavior
            ],
            buttonClicked: function() {
              this.registerTranslation('en', {
                original: 'changed'
              });
              this.selectLanguage('en');
            }
          });
        </script>
      </dom-module>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-04
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-19
      相关资源
      最近更新 更多