如何轻松确定$ scope中添加/删除的内容。$ watch?

时间:2014-09-03 16:36:57

标签: javascript jquery angularjs data-binding angularjs-directive

我的任务是在Angular指令中包装一个JQuery样式的UI组件。我完成了任务,但看起来很丑陋。底层组件的API仅具有addremove方法,用于控制项目列表。我唯一能想到的就是用scope.$watchCollection观察传递给我的指令的双向绑定变量,然后遍历旧参数和新参数以确定添加或删除的内容,然后调用add / remove API调用底层组件。这有效,但我很好奇是否有更好的方法来实现这一目标。这段代码很丑陋而令人困惑。

以下是该组件自然栖息地中的组件演示最小化:

http://codepen.io/Chevex/pen/ofGeB?editors=101

您可以看到组件在包含标记中列表中项目的元素上实例化。然后,组件返回API以添加/删除单个项目。请注意,我无法控制实际应用程序中的底层组件,并且真实组件的功能远远超过我的演示组件(可以使用ng-repeat轻松重写)。

这是我的指令包装器的演示最小重新创建:

http://codepen.io/Chevex/pen/LDgCF?editors=101

这非常有效并且使用jquery样式的组件模拟双向绑定变量,该组件仅具有单个项目的添加/删除方法。我想知道是否有更好的方法来确定$watchCollection中的新/已删除项目。

  // Watch items for changes.
  scope.$watchCollection('items', function (newItemList, oldItemList) {
    // Iterate over the newItemList and determine what items are new.
    if (newItemList) {
      newItemList.forEach(function (newItem) {
        var addItem = true;
        if (oldItemList) {
          oldItemList.forEach(function (oldItem) {
            if (newItem === oldItem) {
              addItem = false;
            }            
          });
        }
        if (addItem) {
          listApi.addItem(newItem);
        }
      });
    }
    // Iterate over the oldItemList and determine what was removed.
    if (oldItemList) {
      oldItemList.forEach(function (oldItem, oldItemIndex) {
        var removeItem = true;
        if (newItemList) {
          newItemList.forEach(function (newItem) {
            if (oldItem === newItem) {
              removeItem = false;
            }
          });
        }
        if (removeItem) {
          listApi.removeItem(oldItemIndex);
        }
      });
    }
  });

所有这些只是为了确定每当集合发生变化时应该使用组件API添加或删除的内容。这是最好的方法吗?我问,因为我一直在发现自己反复写出类似的逻辑,并想知道是否有更合适和/或更简单的方法来做这件事。

1 个答案:

答案 0 :(得分:1)

您可以使用以下内容:

Array.prototype.diff = function(arr) {
    return this.filter(function(el) { return arr.indexOf(el) < 0; });
};

var addedItems = newItemList.diff(oldItemList);
var removedItems = oldItemList.diff(newItemList);