为什么元素仅限于Polymer 1.x中的一个实例?

时间:2016-02-05 21:43:41

标签: polymer polymer-1.0

我创建了一个名为<us-map-select>的自定义元素,并希望在我的应用中使用它两次。像这样:

<us-map-select></us-map-select>
<us-map-select></us-map-select>

当我使用它一次(如下)时,它可以工作。

<us-map-select></us-map-select>

但是当我使用它两次(如下所示)时,应用程序会断开,我会看到一个空白页面。

<us-map-select></us-map-select>
<us-map-select></us-map-select>

我认为这可能与我的代码中的以下某些行有关,这些行在多个实例正在运行时可能会发生冲突。可能存在问题的行如下......

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
...
google.charts.setOnLoadCallback(this._drawRegionsMap.bind(this));

The full code can be seen in this jsBin(及以下):

问题

  

任何人都可以告诉我可能导致我的元素的第二个同步实例导致&#34; break&#34;我的应用程序?

http://jsbin.com/gihezatigo/1/edit?html,console,output
<!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="iron-selector/iron-selector.html" rel="import">

  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript" src="https://www.google.com/jsapi"></script>

</head>

<body>

  <dom-module id="x-element">

    <template>
      <style>
        #geochart {
          width: 100%;
          max-height: 500px;
        }
      </style>
      <button on-tap="_show">Show</button>
      <button on-tap="clearAll">Clear All</button>
      <button on-tap="selectAll">Select All</button>
      <div id="geochart"></div>
      <div hidden id="selectMirror">
        <iron-selector id="selector" activate-event="" selected-values="{{selectedStates}}" multi attr-for-selected="name">
          <template is="dom-repeat" items="[[items]]">
            <span name="[[item.0]]"></span>
          </template>
        </iron-selector>
      </div>
    </template>

    <script>
      (function(){
        Polymer({
          is: 'x-element',
          properties: {
            items: {
              type: Array,
              notify: true,
              value: function() {
                return [['State', 'Select'], ['Alabama', 0], ['Alaska', 0], ['Arkansas', 0], ['Arizona', 0], ['California', 0], ['Colorado', 0], ['Connecticut', 0], ['Delaware', 0], ['Florida', 0], ['Georgia', 0], ['Hawaii', 0], ['Iowa', 0], ['Idaho', 0], ['Illinois', 0], ['Indiana', 0], ['Kansas', 0], ['Kentucky', 0], ['Louisiana', 0], ['Massachusetts', 0], ['Maryland', 0], ['Maine', 0], ['Michigan', 0], ['Minnesota', 0], ['Missouri', 0], ['Mississippi', 0], ['Montana', 0], ['North Carolina', 0], ['North Dakota', 0], ['Nebraska', 0], ['New Hampshire', 0], ['New Jersey', 0], ['New Mexico', 0], ['Nevada', 0], ['New York', 0], ['Ohio', 0], ['Oklahoma', 0], ['Oregon', 0], ['Pennsylvania', 0], ['Rhode Island', 0], ['South Carolina', 0], ['South Dakota', 0], ['Tennessee', 0], ['Texas', 0], ['Utah', 0], ['Virginia', 0], ['Vermont', 0], ['Washington', 0], ['Wisconsin', 0], ['West Virginia', 0], ['Wyoming', 0]];
              }
            },
            options: {
              type: Object,
              notify: true,
              value: {
                region: 'US',
                displayMode: 'regions',
                resolution: 'provinces',
                legend: 'none',
              }
            },
            chart: {
              type: Object,
              notify: true,
              //computed: '_computeChart()',
            },
            selectedStates: {
              type: Array,
              notify: true,
              reflectToAttribute: true,
              value: function () {
                return [];
              }
            },
          },

          observers: [
            '_selectedChanged(selectedStates.*)'
          ],

          _selectedChanged: function () {
            this.items.forEach(function (stateItem, index) {
              if (!index) return;
              this.set('items.' + index + '.1', 0);
            }.bind(this));
            this.selectedStates.forEach(function (selectedState) {
              var index = null;
              this.items.some(function (state, stateIndex) {
                if (state[0] === selectedState) {
                  index = stateIndex;
                  return true;
                }
                return false;
              });
              this.set('items.' + index + '.1', 1);
            }.bind(this));

            this.selectedStates.sort();

            if (google.visualization && this._renderMap) {
              this._drawRegionsMap();
            } else {
              this._renderMap = true;
            }
          },

          _computeChart: function() {
            var out = new google.visualization.GeoChart(this.$.geochart);
            google.visualization.events.addListener(out, 'select', this._selectHandler.bind(this));
            return out;
          },

          get data() {
            return google.visualization.arrayToDataTable(this.items);
          },

          ready: function(){
            google.charts.load('current', {
              'packages': ['geochart']
            });
            google.charts.setOnLoadCallback(this._drawRegionsMap.bind(this));

          },

          clearAll: function() {
            this.set('selectedStates', []);
          },

          selectAll: function() {
            var ar = [],
                a = this.items,
                i = a.length;
            while(i---1){
              ar.push(a[i][0]);
            }
            ar.sort();
            this.set('selectedStates', ar);
          },

          _drawRegionsMap: function() {
            this.set('chart', this._computeChart());
            this.chart.draw(this.data, this.options);
          },
          _selectHandler: function() {
            var selectedItem = this.chart.getSelection();
            var row = selectedItem[0].row;
            var value = this.data.getValue(row, 0);
            this._renderMap = false;
            this.$.selector.select(value);
          },
          _show: function() {
            //console.log(this.items);
            //console.log(this.data);
            //console.log(this.chart);
            console.log(this.selectedStates);
          },
        });
      })();
    </script>

  </dom-module>

  <x-element selected-states='["Ohio"]'></x-element>

</body>

2 个答案:

答案 0 :(得分:3)

您不得多次拨打google.charts.load。一个粗略的解决方案是创建一个闭包变量作为标志来同步图表api的加载状态。

所以,在你已经有一个闭包的顶部:

  (function(){
    var chartStatus = '';

然后添加_syncChartApi方法来处理状态。

      ready: function(){
        this._syncChartApi();
      },

      _syncChartApi: function() {
        switch (chartStatus) {
          case '':
            chartStatus = 'loading'
            google.charts.load('current', {
              'packages': ['geochart']
            });
          case 'loading':
            google.charts.setOnLoadCallback(function() {
              chartStatus = 'loaded';
              this._drawRegionsMap();
            }.bind(this));
            break;
          case 'loaded':
            this._drawRegionsMap();
            break;
        }
      },

http://jsbin.com/pibepis/7/edit?html,output

我提供以上内容主要是为了教育价值。 :)

正如@Tjwato所说,您应该查看官方google-chart实施,因为它具有更复杂的同步。

答案 1 :(得分:1)

据我所知,Google图表API不希望同时运行两个自身实例。 Similar Problem

我建议调查google-chart元素。从我所知道的,它可以做你想要的一切。希望这会有所帮助。