繁体   English   中英

聚合物1.x:数据绑定数组

[英]Polymer 1.x: Databinding Arrays

目的

我想将此元素中selected属性数据绑定到DOM(在<div>[[selected]]</div> )。

选择一个州(例如“德克萨斯州”)后,我希望该州的名称出现在“科罗拉多州,南达科他州”预选州旁边的左上方(在<div>[[selected]]</div>标签)。 但是,事实并非如此。

这里发生了什么? 如何成功将DOM绑定到selected属性? 并让DOM自动随着选中和取消选中的每个新状态进行更新。

重现问题

跟着这些步骤:

  1. 打开此jsBin
  2. 观察预选的州是科罗拉多州和南达科他州。
  3. 注意Colarado和South Dakota在左上方列出。
  4. 单击德克萨斯。
  5. 观察在图表中选择的德克萨斯州。
  6. ❌请注意,在左上方的所选州列表中未包含德克萨斯州。 <div>[[selected]]</div>
  7. 单击标记为“显示值”的按钮,然后在控制台中观察到“ Texas”已包含在selected阵列中。

使用.slice()的尝试解决方案崩溃

这个SO答案解释了为什么Polymer对象不能直接观察到变异数组

@ScottMiles写道:

...您正在做Polymer无法看到的工作(即数组操作),然后要求set找出发生了什么。 但是,当您调用this.set('selected', selected); ,Polymer看到selected的标识没有改变(也就是说,它与以前的Array对象相同),并且只是停止处理。

因此,我尝试通过在原始数组上使用.slice()方法创建一个新数组来解决此问题,如下所示。

http://jsbin.com/yosajuwime/1/edit?html,控制台,输出
 // Sort new 'selected' array _selectedChanged: function(selectedInfo) { var selected = this.selected.slice(); selected.sort(); //this.set('selected', selected); // Uncommenting this line crashes call stack }, 

这似乎解决了可观察性问题,但产生了副作用,并使调用堆栈崩溃。

资源

http://jsbin.com/yosajuwime/1/edit?html,控制台,输出
 <!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() { // google-chart monkey patch 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', /** / * Fired when user selects chart item. * * @event us-map-select * @param {object} detail Alpabetized array of selected state names. /**/ 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, value: 'blue', }, options: { type: Object, computed: '_computeOptions(color)', }, selected: { type: Array, value: function() { return []; } }, data: { type: Array, computed: '_computeData(items, selected.length)' }, }, observers: [ '_selectedChanged(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) { var string = e.path[0].textContent.split('Select')[0].trim(), // eg '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); } }, // Sort new 'selected' array _selectedChanged: function(selectedInfo) { var selected = this.selected.slice(); selected.sort(); //this.set('selected', selected); // Uncommenting this line crashes call stack }, // After 'items' populates or 'selected' changes, compute 'data' _computeData: function(items, selectedInfo) { 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> 

如果要绑定数组,则必须使用dom-repeat。

<template is="dom-repeat" items="[[selected]]">[[item]] </template>

http://jsbin.com/soxedeqemo/edit?html,控制台,输出

dom-repeat的格式不支持正确使用逗号分隔符。 所以我改用了一个计算属性字符串。

http://jsbin.com/ruduwavako/1/edit?html,控制台,输出
 <div>[[selectedString]]</div> ... selectedString: { type: String, computed: '_computeSelectedString(selected.length)', }, ... _computeSelectedString: function(selectedInfo) { return this.selected.sort().join(', '); }, 

数据绑定数组可能很棘手。

因此,这是一个完整的实现示例

http://jsbin.com/xonanucela/edit?html,控制台,输出
 <!doctype html> <head> <meta charset="utf-8"> <base href="https://polygit.org/components/"> <script src="webcomponentsjs/webcomponents-lite.min.js"></script> <link href="paper-button/paper-button.html" rel="import"> </head> <body> <x-element></x-element> <dom-module id="x-element"> <template> <br><br> <paper-button on-tap="_addNew">Click To Add</paper-button> <p> <strong>Items</strong>: <template is="dom-repeat" items="{{items}}"> <span>[[item]] </span> </template> </p> </template> <script> Polymer({ is: 'x-element', properties: { items: { type: Array, value: function() { return ['foo']; } } }, _addNew: function() { var a = this.items; // Clones array a.push('bar'); // Updates "value" console.log('a', a); this.set('items', a.slice()); // Updates "identity" console.log('items', this.items); }, }); </script> </dom-module> </body> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM