当前位置: 首页 > 面试题库 >

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

姜博
2023-03-14
问题内容

我做了一个设计为使用ngModel指令附加到元素的指令。如果模型的值与某物匹配,则应将其设置为先前的值。在我的示例中,我正在寻找“
foo”,如果输入的是它,则将其设置回前一个。

我的单元测试在此方面通过的很好,因为它们仅查看模型值。但是在实践中,当“放回”触发器时,不会更新DOM。我们最好的猜测是,设置旧==新可以防止脏检查的发生。我逐步完成了$
setViewValueValue方法,它似乎在做应做的事情。但是,直到设置新值后显式调用ngModel。$
render(),它才会更新DOM(以及您在浏览器中看到的内容)。它工作正常,但我只想看看是否有更合适的方法可以做到这一点。

代码如下,这是一个小玩意儿。

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';
}

问题答案:

我们最好的猜测是设置旧==新可以防止脏检查的发生

仅当正在监听的表达式的值发生更改时,才会调用观察者监听器。但是由于您已将模型改回其先前的值,因此不会再次调用它,因为好像值根本没有改变。但是要小心:在监视同一属性的观察者内部更改属性的值可能导致无限循环。

但是,直到设置新值后显式调用ngModel。$ render(),它才会更新DOM(以及您在浏览器中看到的内容)。

没错
$setViewValue设置模型值,就好像视图已更新该模型值一样,但是您需要调用$render以基于(新)模型值有效地呈现视图。查看此讨论以获取更多信息。

最后,我认为您应该以其他方式解决问题。您可以使用的$parsers属性NgModelController来验证用户输入,而不是使用观察者:

link: function (scope, element, attrs, 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脚本更改为使用上面的代码。

angular.module('myDirective', [])

.directive('myDirective', function () {

  return {

    restrict: 'A',

    terminal: true,

    require: "?ngModel",

    link: function (scope, element, attrs, 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>


 类似资料:
  • 问题内容: 我创建了一个用于显示工具提示的指令: 对应功能: 应用于此: 这是我观点的一部分,由拥有者的控制器处理 为什么必须调用才能将更改应用到,该更改是早先声明和初始化的? 问题答案: 因为附加到事件的回调超出了angular的范围;angular不知道该函数何时运行/结束,因此摘要循环永远不会运行。 调用或告诉angular更新绑定并触发任何手表。

  • 问题内容: 我知道我可以使用serialVersionUID来控制类的版本。我读到我可以添加或删除字段,并且该类仍将兼容,它将仅使用默认值。 什么时候 必须 更改serialVersionUID? 问题答案: 当对类的结构进行不兼容的更改时,最好更改serialVersionUID字段的值。Java对象序列化规范中列出了不兼容更改的完整列表。 为了进一步扩展,对类的不兼容更改将阻止反序列化机制创建

  • 问题内容: 我试图做一个简单的指令来显示名称并允许对其进行更改。当我在名称页上放置多个指令时,它们似乎都共享name属性。我究竟做错了什么? 问题答案: 如前面的答案中所述,AngularJS指令的默认行为是共享它们所包含的范围。此行为通过指令定义对象中的参数进行更改。 您可以在AngularJS文档的此部分中查看scope参数的文档:http : //docs.angularjs.org/api

  • 问题内容: 我想在3个地方使用相同的HTML模板,只是每次使用不同的模型。我知道我可以从模板访问变量,但是名称会有所不同。 有没有办法将模型传递给ngInclude? 这是我想要实现的,当然add-variable属性现在不起作用。然后,在我包含的模板中,我将访问detailsObject及其属性。 如果我使用ng-include的方法不好,还有其他应该尝试的方法吗? 问题答案: 注意:这不是我的

  • 问题内容: 每个人都告诉我“使用super.viewDidLoad()因为它就是这样”或“我一直那样做,所以要保留它”,“如果不叫super就是错误的”等。 我只发现了一些有关Objective-C用例的主题,这些主题并没有那么启发性,但是我正在Swift 3中进行开发,所以有什么专家可以给我一个很好的详细解释吗? 这是一种良好实践的案例还是有任何隐藏的影响? 问题答案: 通常,最好为您覆盖的所有

  • 问题内容: 我有一个AngularJS属性指令,并且只要其父输入的值发生更改,我都想采取措施。现在,我正在使用jQuery: 没有jQuery,有没有办法做到这一点?我发现keyPress事件并没有完全实现我想要的功能,虽然我确定自己会提出解决方案,但是当我在Angular项目中使用jQuery时,我会有些紧张。 那么,Angular如何做到这一点呢? 问题答案: AngularJS文档中有一个很