gpt4 book ai didi

javascript - Angularjs 无限摘要循环与 ng-repeat 和过滤器

转载 作者:行者123 更新时间:2023-12-03 16:27:00 24 4
gpt4 key购买 nike

我在 angularjs 中创建了一个自定义过滤器,它按日期对我的元素进行分组。

这是 HTML 部分:

<table ng-repeat="(index, groupData) in something = (recentTasks | groupBy:dataGroupBy) track by $index">

过滤器看起来像这样:

module.filter('groupBy', function () {
return function(items, field) {
var groups = [];

switch (field) {
case 'week':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateWeeksBack(date);

if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateWeeksBack(date),
tasks: []
};
}

groups[back].tasks.push(item);
groups[back].total_time += item.time;
});

break;

case 'month':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateMonthsBack(date);

if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateMonthsBack(date),
tasks: []
};
}

groups[back].tasks.push(item);
groups[back].total_time += item.time;
});

break;

default:
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateDaysBack(date);

if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateDaysBack(date),
tasks: []
};
}

groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
}
return groups;
}
});

它的作用 - 输入 (recentTasks) 是一组任务。每个任务都定义了一个“日期”参数。我需要按日期分隔这些任务——每天都会在单独的表格中。它有效,但我得到无限摘要循环。

你能帮我解决一下我的问题吗?或者有更好的解决方案吗?

编辑:输入输出示例:

$scope.items = [
{name: 'Abc', date: '2014-03-12'},
{name: 'Def', date: '2014-03-13'},
{name: 'Ghi', date: '2014-03-11'},
{name: 'Jkl', date: '2014-03-12'}
]

输出必须像这样分组:

[
'2013-03-11': [
{name: 'Ghi'}
],
'2013-03-12': [
{name: 'Abc'},
{name: 'Jkl'}
],
'2013-03-13': [
{name: 'Def'}
]
]

因为每一天的项目都在 HTML 结构的单独表格中。

<table ng-repeat="dayData in groupBy(items, 'day')">
<thead>
<tr><td>{{ dayData.date }}</td> </tr>
</thead>
<tbody>
<tr ng-repeat="item in dayData.items">
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>

最佳答案

要理解为什么会发生这种情况,您需要了解摘要循环。 Angular 基于“脏检查”,摘要循环是 Angular 遍历范围内的所有属性以查看哪些属性发生了变化。如果任何属性发生变化,它会触发所有监视这些属性的事件,让它们知道发生了某些事情。由于 watch 可以更改范围的属性,因此 Angular 在 watch 完成后运行另一轮脏检查。摘要循环在遍历所有属性并且发现它们都没有更改时停止。当 watch 总是为属性设置新值时,就会出现无限摘要。这样的事情可能会更好地解释它:

$scope.myNumber = Math.random();
$scope.$watch('myNumber', function() {
$scope.myNumber = Math.random();
});

也就是说,我们的 watch 永远不会停止被调用,因为它总是在改变 myNumber 的值。错误的另一个常见原因是当您有两个属性和两个 watch 时,如下所示:

$scope.prop1 = Math.random();
$scope.prop2 = Math.random();

$scope.$watch('prop1', function() {
$scope.prop2 = Math.random();
});
$scope.$watch('prop2', function() {
$scope.prop1 = Math.random();
});

这些 watch 会在无限循环中相互触发。

那么在您的情况下发生的情况是您的过滤器总是返回一个包含新对象的新数组。 Angular 不会通过检查所有属性并比较它们来比较对象,而是添加一个 $$hashkey 属性并使用它来与其他对象进行比较。如果两个对象具有相同的 $$hashkey 属性,则认为它们相等。因此,即使您每次都返回相同的数据结构,Angular 也会将其视为一个新对象并运行另一个摘要循环,直到它放弃。

因此,为了让您的过滤器正常工作,您需要更改代码,以便对于传入的相同参数,它会返回一个包含相同对象的数组,就像对这些对象的相同引用一样。这应该足以确保您不会总是为 groups[back] 创建新对象,而是重复使用以前的对象。

编辑:

好吧,我要让你失望了,我建议你重新考虑你的过滤器。对于其他开发人员(或一年后的你自己)来说,你在 ng-repeat 上设置了一个过滤器,它不会返回要重复的列表子集,而是返回一个新的数据结构代替。举个例子:

// Controller
$scope.items = [
{name: 'Buy groceries', time: 10},
{name: 'Clean the kitchen', time: 20}
];

// Template
<li ng-repeat="item in items | groupBy:something">
{{item.total_time}}
</li>

有人会查看 Controller 以查看 item 包含的内容,他们会看到它有一个 name 和一个 time 属性。然后他们查看模板,发现有一个 total_time 属性,他们不知道它来自 groupBy 过滤器,因为 Angular 中的过滤器通常不知道改变对象。

我认为你应该做的是将你的分组代码提取到你的范围内的一个函数中(或创建一个服务),并且只使用过滤器来过滤掉不相关的项目。

这样,您的模板将看起来像这样:

<li ng-repeat="item in groupBy(items, 'something')">
{{item.total_time}}
</li>

这样就不会那么困惑了,因为很明显 groupBy() 方法返回了一个新的数据结构。它还会为您修复无限摘要错误。

关于javascript - Angularjs 无限摘要循环与 ng-repeat 和过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22405659/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com