Polymer 1.x:Obervers 错误?修复或解决方法?
Polymer 1.x: Obervers bug? Fix or Workaround?
首先让我说,我 90% 确定这是 Polymer 观察者系统的错误。
进行以下测试并注意以下意外行为:
测试程序
- Open this JSBin.
- 切换
<paper-toggle-button>
。
- 请注意
changes
变量 没有 像预期的那样递增。
- 在
<paper-input>
字段中输入任何文本。
- 注意
changes
变量 确实 按预期增加。
- 再次切换
<paper-toggle-button>
。
- 请注意
changes
变量 现在 按预期递增。
请注意,我也观察到 <paper-dropdown-menu>
存在与 <paper-toggle-button>
相同的问题,但为简洁起见,在此问题中省略了它。
问题
- What's going on here?
- Is this a bug?
- Is there any workaround or fix?
http://jsbin.com/saxewimowu/edit?html,输出
<html>
<head>
<title>My Element</title>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
<base href="http://element-party.xyz/" />
<link rel="import" href="all-elements.html" />
</head>
<body>
<dom-module id="my-element">
<template>
<paper-input value="{{str::input}}"></paper-input><br />
<paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
<br />changes:<span>[[num]]</span><br />
<br />str: <span>[[str]]</span><br />
<br />bool:<span>[[bool]]</span><br />
</template>
<script>
(function() {
Polymer({
is: 'my-element',
observers: [
'inputChanged(str, bool)'
],
inputChanged(a, b) {
if(! this.num){
this.set('num', 1);
} else {
this.set('num', (this.num + 1) );
}
}
});
})();
</script>
</dom-module>
<my-element></my-element>
</body>
</html>
它在两个属性的值都不同 undefined
(我猜是 null
)之后执行。
输入文本并单击切换按钮后,每次更改都会打印 A
。
要变通为您的属性分配默认值。
我加了
properties: {
str: {
type: String,
value: ''
},
bool: {
type: Boolean,
value: false
}
},
根据您的要求,我无法再重现您的问题。
解决方法是单独观察道具。
(function() {
Polymer({
is: 'my-element',
properties: {
str: {
type: String,
notify: true,
observer: '_somethingChanged'
},
bool: {
type: Boolean,
notify: true,
observer: '_somethingChanged'
}
},
_somethingChanged: function(evt) {
// At this point, evt contains infos about what changed. Eg path and value.
console.log('Something changed');
},
});
})();
另一种解决方法是使 str
和 bool
成为同一 属性 的一部分(名为 foo
的对象)并观察 foo.*
。
(function() {
Polymer({
is: 'my-element',
properties: {
foo: {
type: Object,
notify: true,
value: function(){
return {
str: 'Default',
bool: false
}
}
},
},
observers: [ '_somethingChanged(foo.*)' ],
_somethingChanged: function() {
// At this point, evt contains infos about what changed. Eg path and value.
console.log('Something changed');
},
});
})();
为了完整起见,我将添加源代码和this link to the JSBin of the accepted answer and working solution。
http://jsbin.com/pufalegofe/1/edit?html,输出
<html>
<head>
<title>My Element</title>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
<base href="http://element-party.xyz/" />
<link rel="import" href="all-elements.html" />
</head>
<body>
<dom-module id="my-element">
<template>
<paper-input value="{{str::input}}"></paper-input><br />
<paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
<br />changes:<span>[[num]]</span><br />
<br />str: <span>[[str]]</span><br />
<br />bool:<span>[[bool]]</span><br />
</template>
<script>
(function() {
Polymer({
is: 'my-element',
properties: {
str: {
type: String,
value: ''
},
bool: {
type: Boolean,
value: false
}
},
observers: [
'inputChanged(str, bool)'
],
inputChanged: function(a, b) {
if(! this.num){
this.set('num', 1);
} else {
this.set('num', (this.num + 1) );
}
}
});
})();
</script>
</dom-module>
<my-element></my-element>
</body>
</html>
首先让我说,我 90% 确定这是 Polymer 观察者系统的错误。
进行以下测试并注意以下意外行为:
测试程序
- Open this JSBin.
- 切换
<paper-toggle-button>
。 - 请注意
changes
变量 没有 像预期的那样递增。 - 在
<paper-input>
字段中输入任何文本。 - 注意
changes
变量 确实 按预期增加。 - 再次切换
<paper-toggle-button>
。 - 请注意
changes
变量 现在 按预期递增。
请注意,我也观察到 <paper-dropdown-menu>
存在与 <paper-toggle-button>
相同的问题,但为简洁起见,在此问题中省略了它。
问题
http://jsbin.com/saxewimowu/edit?html,输出
- What's going on here?
- Is this a bug?
- Is there any workaround or fix?
<html>
<head>
<title>My Element</title>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
<base href="http://element-party.xyz/" />
<link rel="import" href="all-elements.html" />
</head>
<body>
<dom-module id="my-element">
<template>
<paper-input value="{{str::input}}"></paper-input><br />
<paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
<br />changes:<span>[[num]]</span><br />
<br />str: <span>[[str]]</span><br />
<br />bool:<span>[[bool]]</span><br />
</template>
<script>
(function() {
Polymer({
is: 'my-element',
observers: [
'inputChanged(str, bool)'
],
inputChanged(a, b) {
if(! this.num){
this.set('num', 1);
} else {
this.set('num', (this.num + 1) );
}
}
});
})();
</script>
</dom-module>
<my-element></my-element>
</body>
</html>
它在两个属性的值都不同 undefined
(我猜是 null
)之后执行。
输入文本并单击切换按钮后,每次更改都会打印 A
。
要变通为您的属性分配默认值。
我加了
properties: {
str: {
type: String,
value: ''
},
bool: {
type: Boolean,
value: false
}
},
根据您的要求,我无法再重现您的问题。
解决方法是单独观察道具。
(function() {
Polymer({
is: 'my-element',
properties: {
str: {
type: String,
notify: true,
observer: '_somethingChanged'
},
bool: {
type: Boolean,
notify: true,
observer: '_somethingChanged'
}
},
_somethingChanged: function(evt) {
// At this point, evt contains infos about what changed. Eg path and value.
console.log('Something changed');
},
});
})();
另一种解决方法是使 str
和 bool
成为同一 属性 的一部分(名为 foo
的对象)并观察 foo.*
。
(function() {
Polymer({
is: 'my-element',
properties: {
foo: {
type: Object,
notify: true,
value: function(){
return {
str: 'Default',
bool: false
}
}
},
},
observers: [ '_somethingChanged(foo.*)' ],
_somethingChanged: function() {
// At this point, evt contains infos about what changed. Eg path and value.
console.log('Something changed');
},
});
})();
为了完整起见,我将添加源代码和this link to the JSBin of the accepted answer and working solution。
http://jsbin.com/pufalegofe/1/edit?html,输出<html>
<head>
<title>My Element</title>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
<script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
<base href="http://element-party.xyz/" />
<link rel="import" href="all-elements.html" />
</head>
<body>
<dom-module id="my-element">
<template>
<paper-input value="{{str::input}}"></paper-input><br />
<paper-toggle-button checked="{{bool}}"></paper-toggle-button><br />
<br />changes:<span>[[num]]</span><br />
<br />str: <span>[[str]]</span><br />
<br />bool:<span>[[bool]]</span><br />
</template>
<script>
(function() {
Polymer({
is: 'my-element',
properties: {
str: {
type: String,
value: ''
},
bool: {
type: Boolean,
value: false
}
},
observers: [
'inputChanged(str, bool)'
],
inputChanged: function(a, b) {
if(! this.num){
this.set('num', 1);
} else {
this.set('num', (this.num + 1) );
}
}
});
})();
</script>
</dom-module>
<my-element></my-element>
</body>
</html>