Polymer和Polymerfire:如何循环观察者的数据?

时间:2017-01-03 04:51:20

标签: firebase polymer firebase-realtime-database observers polymerfire

我有一个简单的<firebase-query>标记,我希望在通过<dom-repeat>显示之前操纵一些数据。例如,我需要将一些字段转换为链接,并解析一些日期。

所以,我需要在数据准备就绪后获取数据,循环遍历每个项目,并更改一些值。

为此,我有一个数据观察者来检测它何时准备就绪。但是,我无法弄清楚如何遍历JavaScript函数中的数据。出于某种原因,for(var i in items)不起作用,尽管这些项目确实存在。

以下是组件:

<dom-module id="cool-stuff">

  <template>

    <firebase-query id="query" path="/items" data="{{items}}"></firebase-query>

    <template is="dom-repeat" items="{{items}}" as="item">
      [[item.name]]<br />
      [[item.date]]<br />
    </template>

  </template>

  <script>
    Polymer({
      is: 'ix-table',
      properties: {
        items: {type: Object, observer: "_itemsChanged"},
      }
      itemsChanged: function(data) {
        // how do I loop through the data received from firebase-query?
        console.log(data);
      }
    });
  </script>

</dom-module>

理想情况下,我想在观察者功能中做的就是:

for(var i in data) {
  obj = data[i];
  obj.name = '<a href="/item/"+obj.key>'+ojb.name+'</a>';
}

但我似乎无法循环访问数据。

在观察者函数中,console.log(data)返回一些奇怪的东西:

Array[o]
0: Object (which contains a proper item)
1: Object (same)
2: Object (same)

更新

以下是console.log(data)返回的屏幕截图(来自观察者内部):

enter image description here

数组似乎填充了所有对象,但它显示为Array [0]。所以它不会让我循环通过它们。

更新2:

感谢arfost,这是解决方案:

<script>
  Polymer({
    is: 'ix-table',
    properties: {
      items: {type: Object},

    }
    observers: [
      '_itemsChanged(items.splices)'
    ],
    _itemsChanged: function(changeRecord) {
      if (changeRecord) {
        changeRecord.indexSplices.forEach(function(s) {
          for (var i=0; i<s.addedCount; i++) {
            var index = s.index + i;
            var item = s.object[index];
            console.log('Item ' + item.name + ' added at index ' + index);
            // do whatever needed with the item here:
            this.items[index].name = "New name";
          }
        }, this);
      }
    },
  });
</script>

3 个答案:

答案 0 :(得分:4)

<firebase-query>结果

请注意<firebase-query>会生成一个对象数组。假设您的数据库包含/notes/<USER_ID>/下的以下项目:

enter image description here

您的<firebase-query>看起来与此相似:

<firebase-query
    id="query"
    app-name="notes"
    path="/notes/[[user.uid]]"
    data="{{notes}}">
</firebase-query>

(其中user绑定到<firebase-auth>.user)。

假设用户已登录,<firebase-query>将使用以下数组填充其data属性(即绑定到notes):

enter image description here

请注意每个对象如何包含$key属性,该属性对应于Firebase控制台的数据库视图中显示的项目键。

然后,您可以直接使用notes迭代<dom-repeat>

<template is="dom-repeat" items="[[notes]]">
  <li>
    <div>key: [[item.$key]]</div>
    <div>body: [[item.body]]</div>
    <div>title: [[item.title]]</div>
  </li>
</template>

绑定到HTML字符串

您应该知道在这种情况下字符串数据绑定是字面上呈现的,因此尝试将name设置为obj.name = '<a href="...">'将呈现文字字符串而不是锚。相反,您应该在模板中声明标记,并在这些标记内绑定keyname属性。所以,你的观察者可以用这个代替:

<template is="dom-repeat" items="{{items}}" as="item">
  <a href$="/item/[[item.key]]">[[item.name]]</a><br />
  [[item.date]]<br />
</template>

迭代数组

以下注释仅在您希望在显示数据之前改变数据时才相关...

在迭代数组时,你应该avoid for..in因为它不能保证迭代的顺序,并且因为它可能会迭代可能不一定关心的可枚举属性。相反,您可以使用for..of(假设您的应用可以使用ES6):

for (let note of notes) {
  note.title += ' ...';
}

Array.prototype.forEach()

notes.forEach(function(note) {
  note.title += ' ...';
});

答案 1 :(得分:2)

我认为我遇到了和你一样的问题。

它来自firebase查询获取数组的方式,聚合物观察者的工作方式,以及javascript控制台在显示对象时基于参考的事实所隐藏。

事实上,这里真正发生的是,firebase查询正在创建一个空数组,它会触发聚合物观察者。

因此,一旦创建了数组,就会调用你的函数,但是仍然是空的,你不能迭代,因为它是空的。然后记录它,正确显示基元子属性(array [0])

然后firebase开始使用数据填充数组。数组引用保持不变,因此聚合物不会再次触发观察者,并且在控制台中,当它尝试显示数组时,它会显示日志中引用的数组,现在包含数据。

我建议您使用数组变异观察器代替简单的变异观察器,如下所示

`properties: {
    items: {type: Object},
  },
,
observers: [
       '_itemsChanged(items.splices)'
],`

每次将对象添加到数组时都会触发,您将能够完成所需的工作:)

我有关于数组变异观察者文档的链接:) polymer array mutation observer

我希望这能解决你的问题, 祝你有个美好的一天。

答案 2 :(得分:0)

我认为我不能想到你需要通过循环遍历数组而不仅仅是使用计算绑定来改变数据的场景。像这样:

test_cases/test