javascript - 跨自定义元素共享行为状态

标签 javascript internationalization polymer polymer-1.0

我有这两个自定义 polymer 元素 ( 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>

最佳答案

首先,虽然概念是让行为成为实例之间共享数据的管道,但正如所写的那样,每个实例都将拥有自己的translations对象副本,并且kick 属性。

其次,即使该数据被私有(private)化以便可以共享,通过 localize(label, kick) 进行的 kick 绑定(bind)也与表达式处于不同的范围内修改 kick (即 this.set('kick', this.kick + 1); [{sic} 这可以简单地是 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>

关于javascript - 跨自定义元素共享行为状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30746900/

相关文章:

jsf - 以编程方式访问 JSF 应用程序中的属性文件

internationalization - Wicket 中表单组件的国际化标签

javascript - jQuery 无法从 $(this) 按钮单击获取 id

javascript - 如何为嵌入制作随机颜色 Discord.js

cakephp - 事后应用 CakePHP 的翻译行为

javascript - 更改具有相同功能的多个切换按钮标签之一 - polymer

html - 如何更改 Polymer 中铁图标的背景颜色?

javascript - querySelectorAll 不返回 DOM 中的所有元素

c# - 模式对话框未关闭

javascript - 递归函数调用前延迟