假设我正在使用一个指令,该指令通过双向绑定(bind)以 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 回调? 显然,如果我选择一个新日期,流程将如下:
  • Watcher #2 被调用 - 它修改 selectedUnixTimestamp
  • Watcher #1 被调用 - 它修改 selectedDate
  • Watcher #2 再次被调用(新对象引用)——它修改了 selectedUnixTimestamp

  • 但除了第一个之外,我不想要任何这些电话。我怎样才能实现它?

    显然,一种方法是执行以下操作:
    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;
    });
    

    但是维护这样的代码很快就变成了 hell 。

    另一种方法是执行以下操作:
    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) {
    

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

    最佳答案

    Angular 框架建立在以下假设之上:
    例如,准备好与 REST 服务同步的某物的真实可信值(value)在模型中只存在一次。

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

    关于javascript - AngularJS - 如何处理圆形 watch ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21638300/

    10-09 21:58