TLDR: poylmer.js と CustomElements.js を掘り下げてみると、実際にどのように動作するかを確認できます (彼らの意図ではないかもしれませんが、少なくともコードでは)。
CustomElements.js には、setAttribute 関数と removeAttribute 関数を一緒にオーバーロードして、changeAttributeCallback 関数を呼び出すこれらの関数がいくつかあります。
function overrideAttributeApi(prototype) {
if (prototype.setAttribute._polyfilled) {
return;
}
var setAttribute = prototype.setAttribute;
prototype.setAttribute = function(name, value) {
changeAttribute.call(this, name, value, setAttribute);
};
var removeAttribute = prototype.removeAttribute;
prototype.removeAttribute = function(name) {
changeAttribute.call(this, name, null, removeAttribute);
};
prototype.setAttribute._polyfilled = true;
}
function changeAttribute(name, value, operation) {
name = name.toLowerCase();
var oldValue = this.getAttribute(name);
operation.apply(this, arguments);
var newValue = this.getAttribute(name);
if (this.attributeChangedCallback && newValue !== oldValue) {
this.attributeChangedCallback(name, oldValue, newValue);
}
}
Polymer.js では、'attributeChanged' は効果的に 'attributeChanged' としてエイリアス化されます。したがって、コールバックが使用されるのは、setAttribute または removeAttribute を使用するときだけです。
個々の属性については異なりますが。これは、polymer.js では、これらの 'myAttributeChanged' 関数がセットアップされる場所です。
inferObservers: function(prototype) {
// called before prototype.observe is chained to inherited object
var observe = prototype.observe, property;
for (var n in prototype) {
if (n.slice(-7) === 'Changed') {
property = n.slice(0, -7);
if (this.canObserveProperty(property)) {
if (!observe) {
observe = (prototype.observe = {});
}
observe[property] = observe[property] || n;
}
}
}
}
したがって、基本的に、「Changed」で終わるプロパティに対して、ポリマーは「Changed」が進行するものに対してオブザーバーを設定します。興味深いことに、これが実際に機能するためにポリマー要素のどこかに定義された属性である必要はありませんが、それは別の話です。