簡體   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