AngularJS - 如何处理圆形手表?

时间:2014-02-07 21:42:47

标签: javascript angularjs

假设我正在使用通过双向绑定以unix时间戳形式给出日期的指令,但还提供了一个日历小部件来更改选择。

日历小部件使用日期对象,我无法更改输入数据格式,我不想重新设置日历以支持unix时间戳。这只是一个例子,问题是与圆形观察者合作的一般方式。

范围看起来像这样:

scope.selectedUnixTimestamp; // this comes from the outside
scope.selectedDate;

scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
    $scope.selectedDate = new Date(newV*1000);
});
scope.$watch('selectedDate', function(newV, oldV) {
    $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
});

我的问题是:我该怎么做以避免额外拨打$ watch回调?显然,如果我选择一个新的日期,流程将会跟随:

  1. 调用观察者#2 - 它修改selectedUnixTimestamp
  2. 观察者#1被调用 - 它修改了selectedDate
  3. 再次调用观察者#2(新对象引用) - 它修改selectedUnixTimestamp
  4. 但除了第一个之外,我不想要任何这些电话。我怎样才能实现它?


    显然,一种方法是做一些事情:

    scope.selectedUnixTimestamp; 
    scope.selectedDate;
    
    var surpressWatch1 = false;
    var surpressWatch2 = false;
    
    scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
        if(surpressWatch1) { surpressWatch1 = false; return; }
        $scope.selectedDate = new Date(newV*1000);
        surpressWatch2 = true;
    });
    scope.$watch('selectedDate', function(newV, oldV) {
        if(surpressWatch2) { surpressWatch2 = false; return; }
        $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
        surpressWatch1 = true;
    });
    

    但是很快就会成为维护代码的地狱。


    另一种方法是做一些事情:

    scope.selectedUnixTimestamp; 
    scope.selectedDate;
    
    scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
        if(newV*1000 === scope.selectedDate.getTime()) { return; }
        $scope.selectedDate = new Date(newV*1000);
    });
    scope.$watch('selectedDate', function(newV, oldV) {
        if(scope.selectedUnixTimestamp*1000 === newV.getTime()) { return; }
        $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
    });
    

    但如果数据转换比* 1000

    更复杂,那可能会非常昂贵

    另一种方法是观察原始值而不是日期对象:

    scope.$watch('selectedDate.getTime()', function(newV, oldV) {
    

    但这仅适用于此特定示例,并未解决一般问题

2 个答案:

答案 0 :(得分:2)

如何使用圆形手表?我想答案是,尽量不要这样做。

你可以试试这个,虽然我相信你的例子有更好的解决方案。

仅使用一个监视功能:

您可以将一个功能用作手表的第一个参数。将调用此函数,直到它返回的值结算(与上次相同)。你可以这样创建一个$ watch:

$scope.$watch(function() {
    return {
        timestamp: scope.selectedUnixTimestamp, 
        date: scope.selectedDate
    }
}, function(newVal, oldVal) { 
    // Note that newVal and oldVal here is on the form of the object you return in the watch function, and hence have properties: timestamp and date.
    // You can compare newVal.date to oldVal.date (same with timestamp) to see which one has actually changed if you need to do that.
}
true);  // You need a deep watch (the true param) to watch the properties on the object

答案 1 :(得分:1)

Angular框架基于以下假设: 例如,准备与REST服务同步的某些东西的真实可信值在模型中存在一次。

记住这一点,你永远不会写圆形观察者。 如果您有两种不同的方法来更改模型值,您可以编写需要ngModelController实例的指令并提供正确的格式化程序和解析器函数。