跨自定义元素的共享行为状态
Shared behavior state across custom elements
我有这两个自定义聚合物元素 (Polymer 1.0.3):
- 显示要翻译的文本。
- 显示触发翻译加载的按钮。
我还有一个 Behavior 保存翻译(json 对象)并包含使翻译成为可能的所有功能。
这是我期望发生的事情:
- 点击元素 2 中的按钮
- 翻译加载到行为中
- 行为中设置了语言选择
- 元素 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>
首先,虽然概念是让 behavior
成为实例之间共享数据的管道,但正如所写的那样,每个实例都将拥有自己的 translations
对象副本和 kick
属性。
其次,即使该数据被私有化以便可以共享,通过 localize(label, kick)
进行的 kick
绑定与修改 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>
我有这两个自定义聚合物元素 (Polymer 1.0.3):
- 显示要翻译的文本。
- 显示触发翻译加载的按钮。
我还有一个 Behavior 保存翻译(json 对象)并包含使翻译成为可能的所有功能。
这是我期望发生的事情:
- 点击元素 2 中的按钮
- 翻译加载到行为中
- 行为中设置了语言选择
- 元素 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>
首先,虽然概念是让 behavior
成为实例之间共享数据的管道,但正如所写的那样,每个实例都将拥有自己的 translations
对象副本和 kick
属性。
其次,即使该数据被私有化以便可以共享,通过 localize(label, kick)
进行的 kick
绑定与修改 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>