在观察AngularJS中的模型更改时,如何忽略初始加载?

Kev*_*man 181 angularjs angularjs-scope

我有一个网页,作为单个实体的编辑器,它作为$ scope.fieldcontainer属性中的深层图形.在我从REST API(通过$ resource)获得响应后,我将一个监视添加到'fieldcontainer'.我正在使用这个手表来检测页面/实体是否"脏".现在我正在使保存按钮反弹,但实际上我想让保存按钮不可见,直到用户弄脏模型.

我得到的是手表的单个触发器,我认为这是因为.fieldcontainer = ...分配在我创建手表后立即发生.我想只是使用"dirtyCount"属性吸收最初的误报,但感觉非常hacky ......而且我认为必须有一种"Angular惯用"方式来解决这个问题 - 我不是唯一一个用手表检测脏模型.

这是我设置手表的代码:

 $scope.fieldcontainer = Message.get({id: $scope.entityId },
            function(message,headers) {
                $scope.$watch('fieldcontainer',
                    function() {
                        console.log("model is dirty.");
                        if ($scope.visibility.saveButton) {
                            $('#saveMessageButtonRow').effect("bounce", { times:5, direction: 'right' }, 300);
                        }
                    }, true);
            });
Run Code Online (Sandbox Code Playgroud)

我只是一直认为,除了用"if(dirtyCount> 0)"保护我的"UI脏"代码之外,必须有一个更清洁的方法...

MW.*_*MW. 477

第一次调用侦听器时,旧值和新值将完全相同.所以这样做:

$scope.$watch('fieldcontainer', function(newValue, oldValue) {
  if (newValue !== oldValue) {
    // do whatever you were going to do
  }
});
Run Code Online (Sandbox Code Playgroud)

这实际上是Angular文档建议处理它的方式:

在观察者注册观察者之后,异步调用侦听器fn(通过$ evalAsync)来初始化观察者.在极少数情况下,这是不合需要的,因为当watchExpression的结果没有改变时会调用监听器.要在侦听器fn中检测此场景,您可以比较newVal和oldVal.如果这两个值相同(===)则由于初始化而调用了监听器

  • 这应该是公认的答案 - 这是有角度的方式 (31认同)
  • 这是不正确的.重点是忽略从"null"到初始加载值的变化,而不是在没有变化时忽略变化. (24认同)
  • 这是错误的,`oldValue`在第一次复飞时将为null. (7认同)
  • 这种方式比@rewritten的回答更惯用 (3认同)

rew*_*ten 114

在初始加载之前设置一个标志,

var initializing = true
Run Code Online (Sandbox Code Playgroud)

然后当第一个$ watch开火时,做

$scope.$watch('fieldcontainer', function() {
  if (initializing) {
    $timeout(function() { initializing = false; });
  } else {
    // do whatever you were going to do
  }
});
Run Code Online (Sandbox Code Playgroud)

该标志将在当前摘要周期结束时拆除,因此下一次更改不会被阻止.

  • 是的,这可行,但比较@MW建议的新旧价值方法.既简单又更具角度惯用语.你能更新接受的答案吗? (16认同)
  • 始终将oldValue设置为等于第一次触发时的newValue,专门添加以避免必须执行此标记hack (2认同)
  • MW的答案实际上是错误的,因为旧值的新值将无法处理旧值未定义的情况. (2认同)

tri*_*tur 41

我意识到这个问题已得到解答,但我有一个建议:

$scope.$watch('fieldcontainer', function (new_fieldcontainer, old_fieldcontainer) {
    if (typeof old_fieldcontainer === 'undefined') return;

    // Other code for handling changed object here.
});
Run Code Online (Sandbox Code Playgroud)

使用标志有效,但有一点代码味道,你不觉得吗?