使用track by强制接合ng-repeat阵列

DJC*_*DJC 5 javascript angularjs

我们的应用程序有一个任务列表,可以增长很大.主要任务列表有一个侧边栏,当选择任务时,可以在侧边栏中编辑它 - 它使用不同的控制器(TasksSidebarCtrl而不是显示列表的TasksCtrl).复制所选任务,然后将其合并回列表.此通信在TasksService中处理.

索引中每个任务的观察者数量巨大,因此我们决定采用不同的方法.

使用一次性绑定大大减少了观察者的数量(实际上,只有子菜单才能编辑/更改任务的状态而不在创建观察者的侧栏中选择它),但因为我们正在使用track by task.id(我认为考虑到我们拥有的过滤器的数量和DOM将改变的频率是必要的),使用splice不会删除并用新的更新任务替换任务 - 我理解这是完整的跟踪点.

有没有办法强制更新这个任务项目惠斯特仍然使用track by和one-time绑定?

tasks-index.html(我删除了过滤器以提高可读性)

<md-list-item my-task-directive ng-repeat="task in TasksCtrl.tasks track by task.id">
Run Code Online (Sandbox Code Playgroud)

TasksCtrl

TasksService.index().then(function(tasks) {
    vm.tasks = tasks.data ? tasks.data : [];   
});

$scope.$on('task-updated', function() {
    var newTask = TasksService.getUpdatedTask();
    $timeout(function() {
        vm.tasks.splice(newTask.index, 1, newTask.task);
    });
});
Run Code Online (Sandbox Code Playgroud)

TaskSidebarCtrl

$scope.$watch(function() {
    return TasksService.getSelectedTask();
}, function (newVal, oldVal) {

    if (newVal !== oldVal) {
        /* Using copy here so index view does not update as we edit */
        vm.selectedTask = angular.copy(newVal);
        vm.index = TasksService.getSelectedTaskIndex();

    }
});

TasksService.update(vm.selectedTask).then(function(data) {
    // notifications etc here, then...
    TasksService.updateTaskInIndex(vm.index, data.data);
});
Run Code Online (Sandbox Code Playgroud)

TasksService

var selectedTask = {};
var indexOfTask;
var updatedTask = {};
var updatedIndex;

this.setSelectedTask = function(task, index) {
    selectedTask = task;
    indexOfTask = index;
};
this.getSelectedTask = function() {
    return selectedTask;
};
this.getSelectedTaskIndex = function() {
    return indexOfTask;
};
this.getUpdatedTask = function() {
        return {
            'index': updatedIndex,
            'task': updatedTask
        };
};
this.updateTaskInIndex = function(index, task) {
    updatedTask = task;
    updatedIndex = index;
    $rootScope.$broadcast('task-updated');
};
Run Code Online (Sandbox Code Playgroud)

在TaskSidebarCtrl 更新函数中使用简单的angular.copy(带目标)而不是TasksService.updateTaskInIndex(vm.index,data.data)意味着由于一次性绑定,索引视图中的一次性绑定属性不会更新.上面的工作没有被task.id跟踪,但我不想在可能的情况下做出这样的牺牲.我也不想牺牲一次性约束.

有解决方法吗?

ysc*_*cik 1

由于track by task.id新更新的任务获得相同的值,因此它不会重建条目的 DOM 元素,并且由于一次性绑定,此现有元素中的表达式不会更新。

使用track by在更新条目时发生变化的表达式将删除旧任务的节点并插入一个新节点,其中将再次计算一次性绑定表达式。一个简单的方法是为任务分配一个tracking_id具有格式的属性"{id}_{version}",其中版本随着每次更新而变化,并使用track by task.tracking_id.