将项目添加到子数组时,聚合物嵌套 dom-重复模板不会更新
Polymer nested dom-repeat templates are not updating when adding items to sub array
上下文
我正在制作一个显示项目列表的页面。该页面列出了从最新到最旧的项目,并首先按年份然后按月份对它们进行分类。它看起来类似于以下示例:
2019
三月
- 列表项
- 列表项 2
二月
- 列表项 3
2018
十月
- 列表项 4
- 列表项目 5
- 列表项目 6
五月
- 列表项目 7
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 元素)。我在数据库中查询一些列表项,遍历每个项目,然后将其添加到相应的月份数组中。
问题
此页面仅加载前 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.
中看到了建议
此外,如果您有比包含项目数组的月份数组更好的建议,那就更好了。
我成功了。它不像 Polymer 那样优雅或惯用,但它确实有效,所以我在这里分享它。
我制作了一个 items
属性 来存储所有项目。然后当我加载一批新的项目时,我将新项目推送到现有项目数组并再次重建整个 years
数组。
据我所知,您正在更改现有数组,这意味着 Polymer 看不出您的 "changed" 数组与前一个数组有任何区别...因为它们都是相同的数组(数组引用,耶!)。
您需要 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);
}
上下文
我正在制作一个显示项目列表的页面。该页面列出了从最新到最旧的项目,并首先按年份然后按月份对它们进行分类。它看起来类似于以下示例:
2019
三月
- 列表项
- 列表项 2
二月
- 列表项 3
2018
十月
- 列表项 4
- 列表项目 5
- 列表项目 6
五月
- 列表项目 7
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 元素)。我在数据库中查询一些列表项,遍历每个项目,然后将其添加到相应的月份数组中。
问题
此页面仅加载前 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.
此外,如果您有比包含项目数组的月份数组更好的建议,那就更好了。
我成功了。它不像 Polymer 那样优雅或惯用,但它确实有效,所以我在这里分享它。
我制作了一个 items
属性 来存储所有项目。然后当我加载一批新的项目时,我将新项目推送到现有项目数组并再次重建整个 years
数组。
据我所知,您正在更改现有数组,这意味着 Polymer 看不出您的 "changed" 数组与前一个数组有任何区别...因为它们都是相同的数组(数组引用,耶!)。
您需要 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);
}