Polymer 和 Polymerfire:如何循环观察者的数据?
Polymer and Polymerfire: how to loop through the data from an observer?
我有一个简单的 <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)
returns 一些像这样的奇怪的东西:
Array[o]
0: Object (which contains a proper item)
1: Object (same)
2: Object (same)
更新:
这是console.log(数据)returns(来自观察者内部)的截图:
数组似乎填充了所有对象,但它显示为数组[0]。所以它不会让我循环遍历它们。
更新二:
感谢 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>
<firebase-query>
结果
请注意,<firebase-query>
生成一个对象数组。假设您的数据库包含 /notes/<USER_ID>/
下的以下项目:
您的 <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
):
请注意每个对象如何包含 $key
属性,它对应于在 Firebase 控制台的 Database 视图中看到的项目键。
然后您可以直接使用 <dom-repeat>
:
迭代 notes
<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="...">'
会呈现文字字符串而不是锚点。相反,您应该在模板中声明标签,并在这些标签内绑定 key
和 name
属性。因此,您的观察者可以替换为:
<template is="dom-repeat" items="{{items}}" as="item">
<a href$="/item/[[item.key]]">[[item.name]]</a><br />
[[item.date]]<br />
</template>
迭代数组
仅当您希望在显示数据之前改变数据时,以下注释才有意义...
迭代数组时,你应该avoid for..in
because it doesn't guarantee order of iteration, and because it may iterate over enumerable properties you might not necessarily care about. Instead, you could use for..of
(假设 ES6 可用于你的应用程序):
for (let note of notes) {
note.title += ' ...';
}
notes.forEach(function(note) {
note.title += ' ...';
});
我想我 运行 遇到了和你一样的问题。
它来自 firebase 查询获取数组的方式,polymer obersvers 的工作方式,并且被 javascript 控制台在显示对象时基于引用的事实所隐藏。
事实上,这里真正发生的是 firebase 查询正在创建一个空数组,这会触发您的聚合物观察器。
因此,您的函数在数组创建后立即被调用,但仍然是空的,您无法迭代,因为它是空的。然后记录它,其中正确显示基元子属性 (array[0])
然后 firebase 开始用数据填充数组。数组引用保持不变,因此聚合物不会再次触发观察者,并且在控制台中,当它尝试显示数组时,它会显示日志中引用的数组,该数组现在包含数据。
我建议您使用数组变异观察器代替简单的观察器,如下所示
`properties: {
items: {type: Object},
},
,
observers: [
'_itemsChanged(items.splices)'
],`
每次将对象添加到您的数组时它都会触发,您将能够完成您需要的工作:)
我有 link 数组变异观察器的文档:)
polymer array mutation observer
希望这能解决您的问题,
祝你有美好的一天。
我想我想不出这样的场景:您需要通过遍历数组而不是仅使用计算绑定来改变数据。像这样:
<template is="dom-repeat" items="{{items}}" as="item">
<child-el date="{{_computeDate(item.date)}}"></child-el><br />
<child-el attr1="{{_someOtherConversion(item.prop1)}}"></child-el><br />
<child-el attr2="{{_iPromiseAnyConversionCanBeDoneLikeThis(item.prop2)}}"></child-el><br />
</template>
<script>
_computeDate: function(item) {
//do date converstion
}
我有一个简单的 <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)
returns 一些像这样的奇怪的东西:
Array[o]
0: Object (which contains a proper item)
1: Object (same)
2: Object (same)
更新:
这是console.log(数据)returns(来自观察者内部)的截图:
数组似乎填充了所有对象,但它显示为数组[0]。所以它不会让我循环遍历它们。
更新二:
感谢 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>
<firebase-query>
结果
请注意,<firebase-query>
生成一个对象数组。假设您的数据库包含 /notes/<USER_ID>/
下的以下项目:
您的 <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
):
请注意每个对象如何包含 $key
属性,它对应于在 Firebase 控制台的 Database 视图中看到的项目键。
然后您可以直接使用 <dom-repeat>
:
notes
<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="...">'
会呈现文字字符串而不是锚点。相反,您应该在模板中声明标签,并在这些标签内绑定 key
和 name
属性。因此,您的观察者可以替换为:
<template is="dom-repeat" items="{{items}}" as="item">
<a href$="/item/[[item.key]]">[[item.name]]</a><br />
[[item.date]]<br />
</template>
迭代数组
仅当您希望在显示数据之前改变数据时,以下注释才有意义...
迭代数组时,你应该avoid for..in
because it doesn't guarantee order of iteration, and because it may iterate over enumerable properties you might not necessarily care about. Instead, you could use for..of
(假设 ES6 可用于你的应用程序):
for (let note of notes) {
note.title += ' ...';
}
notes.forEach(function(note) {
note.title += ' ...';
});
我想我 运行 遇到了和你一样的问题。
它来自 firebase 查询获取数组的方式,polymer obersvers 的工作方式,并且被 javascript 控制台在显示对象时基于引用的事实所隐藏。
事实上,这里真正发生的是 firebase 查询正在创建一个空数组,这会触发您的聚合物观察器。
因此,您的函数在数组创建后立即被调用,但仍然是空的,您无法迭代,因为它是空的。然后记录它,其中正确显示基元子属性 (array[0])
然后 firebase 开始用数据填充数组。数组引用保持不变,因此聚合物不会再次触发观察者,并且在控制台中,当它尝试显示数组时,它会显示日志中引用的数组,该数组现在包含数据。
我建议您使用数组变异观察器代替简单的观察器,如下所示
`properties: {
items: {type: Object},
},
,
observers: [
'_itemsChanged(items.splices)'
],`
每次将对象添加到您的数组时它都会触发,您将能够完成您需要的工作:)
我有 link 数组变异观察器的文档:) polymer array mutation observer
希望这能解决您的问题, 祝你有美好的一天。
我想我想不出这样的场景:您需要通过遍历数组而不是仅使用计算绑定来改变数据。像这样:
<template is="dom-repeat" items="{{items}}" as="item">
<child-el date="{{_computeDate(item.date)}}"></child-el><br />
<child-el attr1="{{_someOtherConversion(item.prop1)}}"></child-el><br />
<child-el attr2="{{_iPromiseAnyConversionCanBeDoneLikeThis(item.prop2)}}"></child-el><br />
</template>
<script>
_computeDate: function(item) {
//do date converstion
}