观察聚合物中的含量变化
Observing Content Changes in Polymer
我正在尝试实现一个新的 Polymer 自定义元素。但是,我想在元素内容更改时触发自定义事件。到目前为止,我的代码如下:
<link rel="import" href="../../lib/polymer/polymer.html">
<polymer-element name="dnd-dropdown" attributes="field">
<template>
<link rel="stylesheet" href="dnd-dropdown.css">
<div id="c">
<div class="dndValue"><content></content></div>
<div class="dndTitle">{{field}}</div>
</div>
</template>
<script>
Polymer({
field: "...",
ready: function () {
this.onMutation(this, this.contentChanged);
},
contentChanged: function (e) {
console.log("contentChanged event fired");
console.log("event = %o", e);
}
});
</script>
</polymer-element>
我的理论是,只要 dndValue 节点发生变化(即元素的内容发生变化),onMutation 就会触发,并且会打印两条控制台消息。但是,当我在 Chrome 中更改 F12 开发人员工具中的元素时,没有任何反应。
观察 Polymer 中内容变化的最佳方法是什么?
我在几乎每一次可能性迭代后都遇到了解决方案,所以这是一个经验性的 "it works" 答案,而不是确定性的 "this is the best way to do it" 类答案。
简短版本:使用自定义 MutationObserver。
这是我最终得到的代码:
ready: function () {
var that = this, observer = new MutationObserver(function (mutations) {
console.debug("Firing textChanged event on field ", that.field, " new value ", mutations[0].target.textContent);
this.fire("textChanged", { field: this.field, value: mutations[0].target.textContent });
}).observe(this, { childList: true, subtree: true, characterData: true });
},
当这是来自 Internet Explorer(技术预览)的 运行 时,总共观察到 3 个 childList 突变。当 运行 从 Chrome(对自定义元素有很好的支持)时,只观察到一个 characterData 突变。结果,我只为第一个似乎总是捕获 "right thing" 的事件触发了新事件。鉴于不同的实现,这可能有点脆弱。
我不知道这在 Firefox 或 Opera 中如何工作。 Caniuse.com 说除了 Opera Mini 之外的所有东西都支持 MutationObserver,所以我可以推测它在 Opera Mini 中不起作用。
Polymer 1.7 的更新方法:
使用以下模板
<template>
<content id="myContent"></content>
</template>
您可以通过
观察节点变化
attached: function() {
Polymer.dom(this.$.myContent).observeNodes(this._nodesChanged);
},
_nodesChanged: function() {
var elements = this.$.myContent.getElements();
for(var i = 0; i < elements.length; i++) {
$(elements[i]).on("change", function(){
this.doStuffWithChangedNodes();
}.bind(this));
}
this.doStuffWithChangedNodes();
},
doStuffWithChangedNodes: function() {
var elements = this.$.myContent.getElements();
// you can loop and work with each element
...
}
我正在尝试实现一个新的 Polymer 自定义元素。但是,我想在元素内容更改时触发自定义事件。到目前为止,我的代码如下:
<link rel="import" href="../../lib/polymer/polymer.html">
<polymer-element name="dnd-dropdown" attributes="field">
<template>
<link rel="stylesheet" href="dnd-dropdown.css">
<div id="c">
<div class="dndValue"><content></content></div>
<div class="dndTitle">{{field}}</div>
</div>
</template>
<script>
Polymer({
field: "...",
ready: function () {
this.onMutation(this, this.contentChanged);
},
contentChanged: function (e) {
console.log("contentChanged event fired");
console.log("event = %o", e);
}
});
</script>
</polymer-element>
我的理论是,只要 dndValue 节点发生变化(即元素的内容发生变化),onMutation 就会触发,并且会打印两条控制台消息。但是,当我在 Chrome 中更改 F12 开发人员工具中的元素时,没有任何反应。
观察 Polymer 中内容变化的最佳方法是什么?
我在几乎每一次可能性迭代后都遇到了解决方案,所以这是一个经验性的 "it works" 答案,而不是确定性的 "this is the best way to do it" 类答案。
简短版本:使用自定义 MutationObserver。
这是我最终得到的代码:
ready: function () {
var that = this, observer = new MutationObserver(function (mutations) {
console.debug("Firing textChanged event on field ", that.field, " new value ", mutations[0].target.textContent);
this.fire("textChanged", { field: this.field, value: mutations[0].target.textContent });
}).observe(this, { childList: true, subtree: true, characterData: true });
},
当这是来自 Internet Explorer(技术预览)的 运行 时,总共观察到 3 个 childList 突变。当 运行 从 Chrome(对自定义元素有很好的支持)时,只观察到一个 characterData 突变。结果,我只为第一个似乎总是捕获 "right thing" 的事件触发了新事件。鉴于不同的实现,这可能有点脆弱。
我不知道这在 Firefox 或 Opera 中如何工作。 Caniuse.com 说除了 Opera Mini 之外的所有东西都支持 MutationObserver,所以我可以推测它在 Opera Mini 中不起作用。
Polymer 1.7 的更新方法:
使用以下模板
<template>
<content id="myContent"></content>
</template>
您可以通过
观察节点变化attached: function() {
Polymer.dom(this.$.myContent).observeNodes(this._nodesChanged);
},
_nodesChanged: function() {
var elements = this.$.myContent.getElements();
for(var i = 0; i < elements.length; i++) {
$(elements[i]).on("change", function(){
this.doStuffWithChangedNodes();
}.bind(this));
}
this.doStuffWithChangedNodes();
},
doStuffWithChangedNodes: function() {
var elements = this.$.myContent.getElements();
// you can loop and work with each element
...
}