Angularjs $watch仅在指令内发射一次

Angularjs $watch仅在指令内发射一次,angularjs,Angularjs,我是angular js的新手,所以请有人帮助我。我在这里有我的模板: <form ng-model="signup" form-valid> <input type="text" name="username" ng-model="signup.username">{{signup}} </form> 当我在文本框中输入一些值时,模型会发生变化,相应地,“$watch”会被触发。但是在这里,当我第一次在文本框中输入任何值时,“$watch”只会触发

我是angular js的新手,所以请有人帮助我。我在这里有我的模板:

<form ng-model="signup" form-valid>
    <input type="text" name="username" ng-model="signup.username">{{signup}}
</form>

当我在文本框中输入一些值时,模型会发生变化,相应地,“$watch”会被触发。但是在这里,当我第一次在文本框中输入任何值时,“$watch”只会触发一次。提前感谢。

一个解决方案是使用如下示例中的ngModel

app.directive("formValid",function(){
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      scope.$watch(function () {
          return ngModel.$modelValue;
        }, function(newValue) {
          console.log(newValue);
        });
      }
    }
  });
编辑:最快的解决方案是跟随黑洞的评论,通过添加
true
将手表更新为深度手表。这是因为您正在查看
signup
属性,但是模型值
username
是signup的一个属性。深度监视将用于监视属性


直接使用
ngModel
,而不是通过
attrs
,或者使用格式化程序或解析器(在我看来,Michaels answer中详述的是更好的解决方案)。

使用
ngModelController
时,查看模型更改的标准方法是创建
格式化程序

link: function(scope, element, attrs, ngModelCtrl) {
    ngModelCtrl.$formatters.push(function(value) {
        // Do something with value
        return value;
    });
}
请记住,只有在直接更改模型时才会触发格式化程序。如果更改来自UI(即用户更改了某些内容),则会触发解析器。因此,您可能也需要这样做:

ngModelCtrl.$parsers.push(function(value) {
    // Do something with value
    return value;
});

我建议您阅读文档,以便准确了解这些管道是如何工作的

但是,如果您只想在模型更改时得到通知(您不想或不需要格式化或解析任何内容),那么您可以做一些更简单的事情:

scope: { model: '=ngModel' },
link: function(scope) {
    scope.$watch('model', function(value) {
        // Do something with value
    });
}

但鉴于您的指令名为
formValid
,我认为使用ngModelController是正确的方法

更新


值得一提的是,ngModelController有一个缺点:它不能很好地处理“引用”类型(例如数组、对象)。您可能想查看模型的属性,而不仅仅是对象本身:
scope.$watch(attrs.ngModel,{…},true)对我有用。第三个参数“true”在做什么。在没有“true”的情况下,它只触发了一次。第三个参数是看“deep”还是不看。例如检查其是否为同一对象或检查对象是否具有所有相同的键/值OP正在查看
attrs.ngModel
的内容,即
signup
,这是一个继承范围变量。是的,很公平,我试图在link函数中区分使用scope和attrs,以避免与继承的作用域混淆。我会更新我的答案,但Michael提供了一个很好的解决方案。谢谢。如果其中一个参数满足您的问题要求,请记住接受答案。谢谢Michael。但有一件事我想知道。当我将第三个参数添加为“true”时,它开始观察模型。但之前为什么它只触发一次?下面的代码适用于我的范围。$watch('model',function(value)){//Do something with value},true);@Nitya第三个参数告诉Angular使用
Angular.equals
来比较值(即,它进行深度比较)。因此,如果需要监视对象并在其某个属性更改时收到通知,则需要设置该参数(以换取某些性能)。这是
ngModelController
的一个缺点:它不会进行这种比较,因此在“值类型”中工作得更好。@Nitya关于手表只触发一次,这是意料之中的。每个手表至少运行一次(如果被监视的属性没有值,则使用未定义的参数),如中所示。
scope: { model: '=ngModel' },
link: function(scope) {
    scope.$watch('model', function(value) {
        // Do something with value
    });
}