AngularJS – 在改变模型值的指令中,为什么我必须调用$render?

前端之家收集整理的这篇文章主要介绍了AngularJS – 在改变模型值的指令中,为什么我必须调用$render?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我制定了一个使用ngModel指令附加到元素的指令。如果模型的值与某个值匹配,则该值应该设置为上一个值。在我的例子中,我正在寻找“foo”,并将其设置回到前一个,如果这是键入的内容

我的单位测试通过了罚款,因为他们只是看模型的价值。但是实际上,当“放回”触发时,DOM不会更新。我们最好的猜测是,设置old == new可防止发生脏的检查。我逐步浏览$ setViewValue方法,它似乎正在做它应该做的事情。但是,在设置新值之后,我将不会更新DOM(以及浏览器中看到的内容),直到我明确地调用ngModel $ render()。它工作正常,但我只是想看看是否有更合适的方法来做到这一点。

代码在下面,here’s a fiddle一样。

angular.module('myDirective',[])
    .directive('myDirective',function () {
    return {
        restrict: 'A',terminal: true,require: "?ngModel",link: function (scope,element,attrs,ngModel) {
            scope.$watch(attrs.ngModel,function (newValue,oldValue) {
                //ngModel.$setViewValue(newValue + "!");   

                if (newValue == "foo")
                {
                    ngModel.$setViewValue(oldValue);   
                    /* 
                        I Need this render call in order to update the input Box; is that OK?
                        My best guess is that setting new = old prevents a dirty check which would trigger $render()
                    */
                    ngModel.$render();
                }
            });
        }
    };
});

function x($scope) {
    $scope.test = 'value here';
}

Our best guess here is that setting old == new prevents a dirty check from happening

监听器监听器只有当其正在监听的表达式的值发生变化时才会调用。但是,由于您将模型更改回以前的值,所以不会再次调用,因为它的值完全没有改变。但是,请小心:更改监视器内部属性的值,监视同一属性可能导致无限循环。

However it won’t update the DOM (and what you see in the browser) until I explicitly call ngModel.$render() after setting the new value.

这是正确的。 $ setViewValue设置模型值,就像它被视图更新一样,但是您需要调用$ render以根据(新)模型值有效地呈现视图。查看this discussion了解更多信息。

最后,我认为你应该以不同的方式来处理你的问题。您可以使用NgModelController的$ parsers属性来验证用户输入,而不是使用观察器:

link: function (scope,ngModel) {
  if (!ngModel) return;

  ngModel.$parsers.unshift(function(viewValue) {
    if(viewValue === 'foo') {                 
      var currentValue = ngModel.$modelValue;
      ngModel.$setViewValue(currentValue);
      ngModel.$render(); 
      return currentValue;
    }
    else 
      return viewValue;
  });
}

我更改了jsFiddle script以使用上面的代码

angular.module('myDirective',[])
.directive('myDirective',function () {
  return {
    restrict: 'A',ngModel) {
      if (!ngModel) return;

      ngModel.$parsers.unshift(function(viewValue) {
        if(viewValue === 'foo') {                 
          var currentValue = ngModel.$modelValue;
          ngModel.$setViewValue(currentValue);
          ngModel.$render(); 
          return currentValue;
        }
        else 
          return viewValue;
      });
    }
  };
});

function x($scope) {
  $scope.test = 'value here';
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>Foo Fighter</h1>
I hate "foo",just try and type it in the Box.
<div ng-app="myDirective" ng-controller="x">
  <input type="text" ng-model="test" my-directive>
  <br />
  model: {{test}}
</div>

猜你在找的Angularjs相关文章