我有一个编写自定义表单指令的小实验。 基于开发人员指南中自定义表单指令的示例,我试图指出您必须用scope.$apply包装$setViewValue调用scope.$apply并显示模型如何在没有它的情况下更新。 但令我惊讶的是我删除了scope.$apply wrap和代码仍然有效。 所以我在角度源代码中进行了一些挖掘,发现通过对支持1.3 ngModelOptions进行了更改, $setViewValue已经调用了scope.$apply现在实际包装它会导致额外的不必要的摘要周期 。 这是angular 1.3.15源代码的实现:
this.$setViewValue = function(value, trigger) { ctrl.$viewValue = value; if (!ctrl.$options || ctrl.$options.updateOnDefault) { ctrl.$$debounceViewValueCommit(trigger); } }; this.$$debounceViewValueCommit = function(trigger) { var debounceDelay = 0, options = ctrl.$options, debounce; if (options && isDefined(options.debounce)) { debounce = options.debounce; if (isNumber(debounce)) { debounceDelay = debounce; } else if (isNumber(debounce[trigger])) { debounceDelay = debounce[trigger]; } else if (isNumber(debounce['default'])) { debounceDelay = debounce['default']; } } $timeout.cancel(pendingDebounce); if (debounceDelay) { pendingDebounce = $timeout(function() { ctrl.$commitViewValue(); }, debounceDelay); } else if ($rootScope.$$phase) { ctrl.$commitViewValue(); } else { $scope.$apply(function() { ctrl.$commitViewValue(); }); }};
这是没有scope.$apply的角度示例 scope.$apply wrapper。
我错过了什么或者有必要更新他们的文档吗? 任何人都可以想到用scope.$apply包装的理由scope.$apply于这种情况?
I had a little experiment with writing a custom form directive. Based on the example for custom form directive in the developer guide I tried to make a point that you have to wrap your $setViewValue call with scope.$apply and show how the model is not updating without it. But to my surprise I removed the scope.$apply wrapping and the code still works. So I did some digging in angular source code and found out that with changes made to support 1.3 ngModelOptions $setViewValue already calls scope.$apply and now actually wrapping it causes an extra unnecessary digest cycle. Here's the implementation from angular 1.3.15 source:
this.$setViewValue = function(value, trigger) { ctrl.$viewValue = value; if (!ctrl.$options || ctrl.$options.updateOnDefault) { ctrl.$$debounceViewValueCommit(trigger); } }; this.$$debounceViewValueCommit = function(trigger) { var debounceDelay = 0, options = ctrl.$options, debounce; if (options && isDefined(options.debounce)) { debounce = options.debounce; if (isNumber(debounce)) { debounceDelay = debounce; } else if (isNumber(debounce[trigger])) { debounceDelay = debounce[trigger]; } else if (isNumber(debounce['default'])) { debounceDelay = debounce['default']; } } $timeout.cancel(pendingDebounce); if (debounceDelay) { pendingDebounce = $timeout(function() { ctrl.$commitViewValue(); }, debounceDelay); } else if ($rootScope.$$phase) { ctrl.$commitViewValue(); } else { $scope.$apply(function() { ctrl.$commitViewValue(); }); }};
and here's angular's example without the scope.$apply wrapper.
So am I missing something or do angular need to update their docs? Can anyone think of a reason to wrap with scope.$apply in this case?
最满意答案
这是使用ngModellController的表单验证器的示例,并且不使用$ scope。$ apply
(function(angular) { var directive = function() { return {`enter code here` require: 'ngModel', link: function($scope, iElm, iAttrs, controller) { // controller.$parsers.push(function(viewValue){ // if (moment( viewValue).isValid()) { console.log($scope); controller.$validators.formDateValidator = function(modelValue, viewValue) { return moment( viewValue).isValid(); }; // return viewValue; //} else { // controller.$setValidity('form-date-validator', false); // return undefined; //} } }; } angular.module('ToDoListApp'). directive('formDateValidator', [directive]); }(window.angular));I wasn't missing anything, as of 1.3 there is no need to call scope.$apply. I actually made a pull request to fix this example and it was accepted and merged.
是否需要在1.3.x上使用scope.apply包装ngModelController。$ setViewValue(Does ngModelController.$setViewValue needs to wrapped with scope.apply on 1.3.x)我有一个编写自定义表单指令的小实验。 基于开发人员指南中自定义表单指令的示例,我试图指出您必须用scope.$apply包装$setViewValue调用scope.$apply并显示模型如何在没有它的情况下更新。 但令我惊讶的是我删除了scope.$apply wrap和代码仍然有效。 所以我在角度源代码中进行了一些挖掘,发现通过对支持1.3 ngModelOptions进行了更改, $setViewValue已经调用了scope.$apply现在实际包装它会导致额外的不必要的摘要周期 。 这是angular 1.3.15源代码的实现:
this.$setViewValue = function(value, trigger) { ctrl.$viewValue = value; if (!ctrl.$options || ctrl.$options.updateOnDefault) { ctrl.$$debounceViewValueCommit(trigger); } }; this.$$debounceViewValueCommit = function(trigger) { var debounceDelay = 0, options = ctrl.$options, debounce; if (options && isDefined(options.debounce)) { debounce = options.debounce; if (isNumber(debounce)) { debounceDelay = debounce; } else if (isNumber(debounce[trigger])) { debounceDelay = debounce[trigger]; } else if (isNumber(debounce['default'])) { debounceDelay = debounce['default']; } } $timeout.cancel(pendingDebounce); if (debounceDelay) { pendingDebounce = $timeout(function() { ctrl.$commitViewValue(); }, debounceDelay); } else if ($rootScope.$$phase) { ctrl.$commitViewValue(); } else { $scope.$apply(function() { ctrl.$commitViewValue(); }); }};
这是没有scope.$apply的角度示例 scope.$apply wrapper。
我错过了什么或者有必要更新他们的文档吗? 任何人都可以想到用scope.$apply包装的理由scope.$apply于这种情况?
I had a little experiment with writing a custom form directive. Based on the example for custom form directive in the developer guide I tried to make a point that you have to wrap your $setViewValue call with scope.$apply and show how the model is not updating without it. But to my surprise I removed the scope.$apply wrapping and the code still works. So I did some digging in angular source code and found out that with changes made to support 1.3 ngModelOptions $setViewValue already calls scope.$apply and now actually wrapping it causes an extra unnecessary digest cycle. Here's the implementation from angular 1.3.15 source:
this.$setViewValue = function(value, trigger) { ctrl.$viewValue = value; if (!ctrl.$options || ctrl.$options.updateOnDefault) { ctrl.$$debounceViewValueCommit(trigger); } }; this.$$debounceViewValueCommit = function(trigger) { var debounceDelay = 0, options = ctrl.$options, debounce; if (options && isDefined(options.debounce)) { debounce = options.debounce; if (isNumber(debounce)) { debounceDelay = debounce; } else if (isNumber(debounce[trigger])) { debounceDelay = debounce[trigger]; } else if (isNumber(debounce['default'])) { debounceDelay = debounce['default']; } } $timeout.cancel(pendingDebounce); if (debounceDelay) { pendingDebounce = $timeout(function() { ctrl.$commitViewValue(); }, debounceDelay); } else if ($rootScope.$$phase) { ctrl.$commitViewValue(); } else { $scope.$apply(function() { ctrl.$commitViewValue(); }); }};
and here's angular's example without the scope.$apply wrapper.
So am I missing something or do angular need to update their docs? Can anyone think of a reason to wrap with scope.$apply in this case?
最满意答案
这是使用ngModellController的表单验证器的示例,并且不使用$ scope。$ apply
(function(angular) { var directive = function() { return {`enter code here` require: 'ngModel', link: function($scope, iElm, iAttrs, controller) { // controller.$parsers.push(function(viewValue){ // if (moment( viewValue).isValid()) { console.log($scope); controller.$validators.formDateValidator = function(modelValue, viewValue) { return moment( viewValue).isValid(); }; // return viewValue; //} else { // controller.$setValidity('form-date-validator', false); // return undefined; //} } }; } angular.module('ToDoListApp'). directive('formDateValidator', [directive]); }(window.angular));I wasn't missing anything, as of 1.3 there is no need to call scope.$apply. I actually made a pull request to fix this example and it was accepted and merged.
发布评论