Mow*_*zer 0 javascript observers polymer polymer-1.0
最终,我想从这个geochart中选择个别状态.但是这个问题仅限于让观察者被标记_computeData
为响应于改变selected
状态数组而被激活.
通过以下步骤重现问题:
请注意控制台显示:
您选择了:科罗拉多州,南达科他州,德克萨斯州
这是预期的这条线:
console.log('You selected: ' + this.selected); // Logs properly
Run Code Online (Sandbox Code Playgroud)
但是,我希望控制台也能读到:
选
按此行:
_computeData: function() {
console.log('selected'); // Does not log properly; function not called?
...
Run Code Online (Sandbox Code Playgroud)
应该由以下一组观察员调用.
http://jsbin.com/wuqugigeha/1/edit?html,console,output...
observers: [
'_computeData(items.*, selected.*)',
'_dataChanged(data.*)',
],
...
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?观察者为什么不调用该_computeData
方法?在改变selected
数组之后可以做些什么来使方法触发?
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="google-chart/google-chart.html" rel="import"> </head>
<body>
<dom-module id="x-element"> <template>
<style>
google-chart {
width: 100%;
}
</style>
<br><br><br><br>
<button on-tap="_show">Show Values</button>
<button on-tap="clearAll">Clear All</button>
<button on-tap="selectAll">Select All</button>
<div>[[selected]]</div>
<google-chart
id="geochart"
type="geo"
options="[[options]]"
data="[[data]]"
xon-google-chart-select="_onGoogleChartSelect">
</google-chart>
</template>
<script>
(function() {
Polymer({
is: 'x-element',
properties: {
items: {
type: Array,
value: function() {
return [ 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming', ].sort();
},
},
color: {
type: String, // '#455A64'
value: function() {
return 'blue';
}
},
options: {
type: Object,
notify: true,
reflectToAttribute: true,
computed: '_computeOptions(color)',
},
selected: {
type: Array,
notify: true,
reflectToAttribute: true,
value: function() {
return [];
},
//observer: '_computeData', // Unsuccessfully tried this
},
data: {
type: Array,
notify: true,
reflectToAttribute: true,
//computed: '_computeData(items.*, selected.*)', // Unsuccessfully tried this
},
},
observers: [
'_computeData(items.*, selected.*)',
'_dataChanged(data.*)',
],
// Bind select event listener to chart
ready: function() {
var _this = this;
this.$.geochart.addEventListener('google-chart-select', function(e) {
this._onGoogleChartSelect(e);
}.bind(_this));
},
_computeOptions: function() {
return {
region: 'US',
displayMode: 'regions',
resolution: 'provinces',
legend: 'none',
defaultColor: 'white',
colorAxis: {
colors: ['#E0E0E0', this.color],
minValue: 0,
maxValue: 1,
}
}
},
// On select event, compute 'selected'
_onGoogleChartSelect: function(e) {
var string = e.path[0].textContent.split('Select')[0].trim(), // e.g. 'Ohio'
selected = this.selected, // Array of selected items
index = selected.indexOf(string);
// If 'string' is not in 'selected' array, add it; else delete it
if (index === -1) {
selected.push(string);
selected.sort();
} else {
selected.splice(index, 1);
}
this.set('selected', selected);
console.log('You selected: ' + this.selected); // Logs properly
// Next step should be '_computeData' per observers
},
// After 'items' populates or 'selected' changes, compute 'data'
_computeData: function() {
console.log('selected'); // Does not log properly; function not called?
var data = [],
items = this.items,
selected = this.selected,
i = items.length;
while (i--) {
data.unshift([items[i], selected.indexOf(items[i]) > -1 ? 1 : 0]);
}
data.unshift(['State', 'Select']);
this.set('data', data);
},
// After 'data' changes, redraw chart
// Add delay to avoid 'google not defined' error
_dataChanged: function() {
var _this = this;
setTimeout(function() {
_this._drawChart();
}.bind(_this), 100)
},
// After delay, draw chart
_drawChart: function() {
var data = this.data,
dataTable = this.$.geochart._createDataTable(data);
console.log(dataTable);
this.$.geochart._chartObject.draw(dataTable, this.options);
},
clearAll: function() {
this.set('selected', []);
},
selectAll: function() {
this.set('selected', this.items);
},
_show: function() {
console.log('items: ' + this.items);
console.log('selected: ' + this.selected);
console.log('data: ' + this.data);
},
});
})();
</script>
</dom-module>
<x-element color="red" selected='["Colorado", "South Dakota"]'></x-element>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
你的问题在这里:
if (index === -1) {
selected.push(string);
selected.sort();
} else {
selected.splice(index, 1);
}
this.set('selected', selected);
Run Code Online (Sandbox Code Playgroud)
Polymer的数据处理方法set
允许您为Polymer提供有关数据更改方式的具体信息,从而允许Polymer进行非常快速的DOM更新.
在这种情况下,你正在做Polymer无法看到它的工作(即数组操作),然后要求set
弄清楚发生了什么.但是,当你调用时this.set('selected', selected);
,Polymer看到它的身份selected
没有改变(也就是说,它与之前的Array对象相同),它只是停止处理.(Fwiw,这是一个常见的问题,所以我们正在考虑进行修改,无论如何都要检查阵列.)
解决方案有两个方面:
1)在对数组进行排序的情况下,为set
via 创建一个新的数组引用slice()
:
if (index === -1) {
selected.push(string);
selected.sort();
this.set('selected', selected.slice());
Run Code Online (Sandbox Code Playgroud)
2)在您只是拼接的情况下,使用splice
辅助函数:
} else {
this.splice('selected', index, 1);
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,您可以避免对数组进行排序,然后this.push
直接使用.
注意:_computeData
正在调用这些更改,但现在它的调用次数太多了.这部分是由于观测selected.*
,这将火selected
,selected.length
和selected.splices
.观察selected.length
而不是selected.*
可能有所帮助.
您的示例还有其他三个主要问题:
data
被绑定到google-chart
(即data="[[data]]"
)所以图表将在data
更改时重绘,我们可以_drawChart
完全删除._computeData(items.*, selected.*)
太激进了,因为它selected.*
会触发'selected.length','selected.splices'和更改selected
.而是使用_computeData(items, selected.length)
.google-chart
本身似乎是马车.特别是,它本身drawChart
没有设置为适当的重入.最明显的问题是,每次绘制图表时,它都会添加一个额外的选择侦听器(这会导致chart-select
在您的应用程序上触发乘法事件).我会欣赏它,如果你将提交Bug上google-chart
,并链接回本左右.:)这是一个修改过的版本,我修补了猴子google-chart.drawChart
,解决了其他两个主要问题,并进行了各种小修.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="google-chart/google-chart.html" rel="import"> </head>
<body>
<dom-module id="x-element"> <template>
<style>
google-chart {
width: 100%;
}
</style>
<br><br><br><br>
<button on-tap="_show">Show Values</button>
<button on-tap="clearAll">Clear All</button>
<button on-tap="selectAll">Select All</button>
<div>[[selected]]</div>
<google-chart
id="geochart"
type="geo"
options="[[options]]"
data="[[data]]"
on-google-chart-select="_onGoogleChartSelect">
</google-chart>
</template>
<script>
(function() {
// monkey-patching google-chart
var gcp = Object.getPrototypeOf(document.createElement('google-chart'));
gcp.drawChart = function() {
if (this._canDraw) {
if (!this.options) {
this.options = {};
}
if (!this._chartObject) {
var chartClass = this._chartTypes[this.type];
if (chartClass) {
this._chartObject = new chartClass(this.$.chartdiv);
google.visualization.events.addOneTimeListener(this._chartObject,
'ready', function() {
this.fire('google-chart-render');
}.bind(this));
google.visualization.events.addListener(this._chartObject,
'select', function() {
this.selection = this._chartObject.getSelection();
this.fire('google-chart-select', { selection: this.selection });
}.bind(this));
if (this._chartObject.setSelection){
this._chartObject.setSelection(this.selection);
}
}
}
if (this._chartObject) {
this._chartObject.draw(this._dataTable, this.options);
} else {
this.$.chartdiv.innerHTML = 'Undefined chart type';
}
}
};
Polymer({
is: 'x-element',
properties: {
items: {
type: Array,
value: function() {
return [ 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming', ].sort();
},
},
color: {
type: String, // '#455A64'
value: 'blue'
},
options: {
type: Object,
computed: '_computeOptions(color)',
},
selected: {
type: Array,
value: function() {
return [];
}
},
data: {
type: Array,
computed: '_computeData(items, selected.length)'
},
},
_computeOptions: function() {
return {
region: 'US',
displayMode: 'regions',
resolution: 'provinces',
legend: 'none',
defaultColor: 'white',
colorAxis: {
colors: ['#E0E0E0', this.color],
minValue: 0,
maxValue: 1,
}
}
},
// On select event, compute 'selected'
_onGoogleChartSelect: function(e) {
console.log('_onGoogleChartSelect: ', e.detail)
var string = e.path[0].textContent.split('Select')[0].trim(), // e.g. 'Ohio'
selected = this.selected, // Array of selected items
index = selected.indexOf(string);
// If 'string' is not in 'selected' array, add it; else delete it
if (index === -1) {
this.push('selected', string);
} else {
this.splice('selected', index, 1);
}
// Next step should be '_computeData' per observers
console.log('_select:', this.selected);
},
// After 'items' populates or 'selected' changes, compute 'data'
_computeData: function(items, selectedInfo) {
console.log('_computeData');
var data = [],
selected = this.selected,
i = items.length;
while (i--) {
data.unshift([items[i], selected.indexOf(items[i]) > -1 ? 1 : 0]);
}
data.unshift(['State', 'Select']);
return data;
},
clearAll: function() {
this.set('selected', []);
},
selectAll: function() {
this.set('selected', this.items);
},
_show: function() {
console.log('items: ' + this.items);
console.log('selected: ' + this.selected);
console.log('data: ' + this.data);
},
});
})();
</script>
</dom-module>
<x-element color="red" selected='["Colorado", "South Dakota"]'></x-element>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
HTH
随机额外的东西:
var _this = this;
setTimeout(function() {
_this._drawChart();
}.bind(_this), 100)
Run Code Online (Sandbox Code Playgroud)
您需要任何捕捉的值this
(_this
)或使用bind
,但它没有任何意义一举两得.
setTimeout(function() {
this._drawChart();
}.bind(this), 100)
Run Code Online (Sandbox Code Playgroud)
... 足够.
归档时间: |
|
查看次数: |
278 次 |
最近记录: |