单向发送数据时聚合物结合

Polymer Binds when Data sent One Way

我目前正在一个项目中使用 Polymer,出于某种原因,我在既不期望也不想要的时候获取数据绑定。

我目前拥有的是一个样板 Polymer 项目,该项目应该包含我创建的新元素(名为 shokka-eval-chart)。这很好用,但不知何故信息正在三个元素之间共享。

为了调试这个问题,我添加了 console.log 消息,告诉我发生了什么。每次控制台日志返回时,都表明 userData 已被修改。这种修改发生在哪里?为什么?

您可能会注意到的一些事情:

  1. 使用一种数据绑定方式发送用户数据::: [[userInfo.evaluations]]
  2. 不应该通知索引我对用户数据的更改::: 通知: false

一些我能想到的可能有问题的地方:

  1. HTML - 我可能没有正确地将东西传递到标签中。
  2. Javascript - 我不知道如何修改用户数据。
  3. 聚合物 - 显而易见的位置。我可能误解了其中一个概念。

请让我知道这是哪里发生的,以及我做错了什么导致发生这种情况。提前致谢。

控制台日志

shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 40
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 0
shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 0
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 -40
shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 -40
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 -80

索引

<body unresolved class="fullbleed layout vertical">
 <span id="browser-sync-binding"></span>
  <template is="dom-bind" id="app">
   <paper-drawer-panel id="paperDrawerPanel">
    <paper-scroll-header-panel main condenses keep-condensed-header>
     <div class="content">
      <iron-pages attr-for-selected="data-route" selected="{{route}}">
       <section data-route="home">
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison1" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison2" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison3" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
       </section>
      </iron-pages>
     </div>
    </paper-scroll-header-panel>
   ...

组件代码

<link rel="import" href="../../bower_components/polymer/polymer.html">

<dom-module id="shokka-eval-chart">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <google-chart id="{{id}}" 
              type="{{type}}" 
              options='{{options}}'
              data='[[data]]'>
    </google-chart>
  </template>
  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'shokka-eval-chart',

      properties: {
        id: {
          type: String
        },
        userEvaluations: {
          type: String
        },
        evalRef: {
          type: String
        },
        userData: {
          type: Array,
          value: [ ["Date", "Professionalism", "Skills", "Work Completion" ],
                   ["Jan 16", 40, 35, 37 ],
                   ["Feb 16", 39, 35, 34 ],
                   ["Mar 16", 38, 36, 39 ],
                   ["Apr 16", 42, 38, 40 ],
                   ["May 16", 42, 37, 41 ],
                   ["Jun 16", 43, 38, 40 ],
                   ["Jul 16", 44, 40, 41 ],
                   ["Aug 16", 45, 43, 42 ],
                   ["Sep 16", 46, 46, 41 ],
                   ["Oct 16", 45, 44, 42 ] ],
          notify: false
        },
        data: {
          type: Array,
          computed: 'computeData(avgData, userData)',
          notify: false
        },
        options: {
          type: Object,
          value: { "title": "Evaluation Comparison" }
        },
        type: {
          type: String,
          value: "column"
        },
        avgData: {
          type: Array,
          value: [ ["Date", "Professionalism", "Skills", "Work Completion" ],
                             ["Jan 16", 40, 40, 40 ],
                             ["Feb 16", 40, 40, 40 ],
                             ["Mar 16", 40, 40, 40 ],
                             ["Apr 16", 40, 40, 40 ],
                             ["May 16", 40, 40, 40 ],
                             ["Jun 16", 40, 40, 40 ],
                             ["Jul 16", 40, 40, 40 ],
                             ["Aug 16", 40, 40, 40 ],
                             ["Sep 16", 40, 40, 40 ],
                             ["Oct 16", 40, 40, 40 ] ],
          notify: false
        }
      },

      computeData: function(avgData, userData){
        console.log(userData[1][0])
        var data = userData.slice();
        console.log(userData[1][1])
        console.log(avgData[1][1])
        console.log(userData[1][1]-avgData[1][1])
        data[1][1] = userData[1][1] - avgData[1][1]
        return data;
      }
  });
  })();
  </script>
</dom-module>

更新: 根据 Günter Zöchbauer 的建议,我已将 var data = userData; 更改为 var data = userData.slice();。然而,这还没有解决问题。我似乎还缺少其他东西。

更新: 在修改数据后查看 userData 后,它似乎仍指向同一个对象。我将 var data = userData.slice(); 更改为

    var data = [];
    for (var i = 0, len = userData.length; i < len; i++) {
      data[i] = userData[i].slice();
    }

为了解决这个问题。这已经解决了我遇到的问题,但仍然让我想知道为什么 userData 是从不同的标签修改的。如果有人可以评论并告诉我为什么会非常感激。

我怀疑你期待这条线

var data = userData;

创建 userData 的副本,但在此行之后,datauserData 指向相同的数据结构。

试试看

var data = userData.splice();

只是猜测。如果这不是问题,我不知道是什么导致了问题。

这可能是它,但我不记得我自己尝试时它是否有效。我在下面用斜体强调。

Configuring default property values

Default values for properties may be specified in the properties object using the value field. The value may either be a primitive value, or a function that returns a value.

If you provide a function, Polymer calls the function once per element instance.

When initializing a property to an object or array value, use a function to ensure that each element gets its own copy of the value, rather than having an object or array shared across all instances of the element.

  data: {
    type: Object,
    value: function() { return {}; }
  }

来源:https://www.polymer-project.org/1.0/docs/devguide/properties#configure-values