我正在制作一个显示项目列表的页面。该页面列出了最新到最旧的项目,并按年份和月份先对其进行分类。看起来类似于以下示例:
三月
2月
十月
可能
HTML的简化版本是:
<template is="dom-repeat" items="{{years}}" as="year">
<span>[[year.name]]</span>
<div id="same-year-items>
<template is="dom-repeat" items="{{year.months}}" as="month">
<span>[[month.name]]</span>
<div id="same-month-items">
<template is="dom-repeat" items="{{month.items}}" as="item">
<custom-list-item item="{{item}}"></custom-list-item>
</template>
</div>
</template>
</div>
</template>
在Javascript文件中,我定义了years
数组属性。 years
中的每年包含一个months
数组,months
中的每个月份包含一个items
数组(请参阅dom-repeat元素)。我在数据库中查询一些列表项,遍历每个项,然后将其添加到相应的month数组中。
此页面仅加载前n个项目。我想在底部有一个“加载更多”按钮,该按钮可以加载接下来的n个项目。 (是的,我知道。无限滚动可能会更好-稍后会出现。即使我使用无限滚动,我仍然会有我要描述的问题。)
当我加载更多项目时,页面不会更新以显示新项目。我知道Polymer对于如何绑定数据非常特别,尤其是当它涉及子属性时。这是Javascript的简化版本,用于将新项目设置为数组:
setItems: function(newItems) {
var tempYearsArray = [];
for (var i = 0, i < this.years.length; i++) {
tempYearsArray.push(this.years[i]);
}
this.set('years', []);
for (var j = 0; j < newItems.length; j++) {
var item = newItems[j];
this.setMonthAndYear(item, tempYearsArray);
}
this.set('years', tempYearsArray);
}
setMonthAndYear: function(item, tempYearsArray) {
var itemDate = new Date(item.lastModified);
var currentYear = itemDate.getFullYear();
var monthIndex = itemDate.getMonth();
var monthName = this.monthNames[monthIndex];
var newYear = true;
var newMonth = true;
for (var i = 0; i < tempYearsArray.length; i++) {
var year = tempYearsArray[i];
if (currentYear === year.name) {
newYear = false;
for (j = 0, j < year.months.length; j++) {
var month = ref[j];
if (monthName === month.name) {
month.items.push(item);
newMonth = false;
break;
}
}
if (newMonth) {
var month = {
items: [item],
name: monthName
};
year.months.push(month);
}
break;
}
}
if (newYear) {
var month = {
items: [item],
name: monthName
};
year = {
name: currentYear,
months: [month]
};
return tempYearsArray.push(year);
}
}
我可以看到years
具有新项目,但是页面仍未呈现它们。我读过其他有类似问题的文章,这是我想到this.set('years', [])
和临时数组的地方。我也尝试过做this.notifyPath('year.months', year.months.slice())
和this.notifyPath('month.items', month.items.slice())
之类的事情。我不确定为什么这行得通,但是我在this Github issues post中看到了建议。
另外,如果您的建议比Years数组更好,那么它更好。
答案 0 :(得分:2)
我知道了。对于Polymer来说,它不那么优雅,或者也许不是惯用的,但是它可以工作,所以我在这里分享。
我创建了一个items
属性,用于存储所有项目。然后,当我加载一批新项目时,将新项目推到现有的项目数组中,然后再次重建整个years
数组。
答案 1 :(得分:1)
据我所知,您正在更改现有数组,这意味着Polymer看不到您“已更改”的数组与上一个数组之间的任何区别……因为它们都是同一数组(数组引用) ,是的!)。
您需要1)创建一个新数组,并用this.set()
替换新数组,2)通过JSON.parse(JSON.stringify(arr)
复制并修改this.set()
该数组,3)使用this.splice()
是因为从理论上讲,它应该起作用,或者4)做您所做的事情:用一个空的数组重置数组,然后用修改后的数组替换。
dom-repeat中的数组子属性更新是在Polymer 2及更高版本中已解决的问题,因为它们删除了脏检查。
另一件事,但不要在for循环内创建变量。在for循环内创建新变量,而不是在外部创建一个然后在循环内重复使用的变量,这是最小的时间损失。
// Your code
for (var j = 0; j < newItems.length; j++) {
var item = newItems[j];
this.setMonthAndYear(item, tempYearsArray);
}
// My suggestion
var item;
for (var j = 0; j < newItems.length; j++) {
item = newItems[j];
this.setMonthAndYear(item, tempYearsArray);
}