【问题标题】:What is the point of controller.$viewValue/controller.$modelValue?controller.$viewValue/controller.$modelValue 的意义何在?
【发布时间】:2015-11-04 19:48:03
【问题描述】:

我不清楚scope.ngModelcontroller.$viewValue/controller.$modelValue/controller.$setViewValue() 之间的关系是什么,具体来说,后三者的意义是什么。例如,见this jsfiddle

<input type="text" ng-model="foo" my-directive>

和:

myApp.directive('myDirective', function($timeout) {
    return {
        require: 'ngModel', 
        restrict: 'A',
        scope: { ngModel: '=' },
        link: function (scope, element, attrs, controller) {
            function log() {
              console.log(scope.ngModel);
              console.log(controller.$viewValue);
              console.log(controller.$modelValue);
            }
            log();
            controller.$setViewValue("boorb");
            log();
            scope.$watch('ngModel', function (val) {
               console.log("val is now", val); 
            });

            $timeout(function () {
                log();
            }, 2000);

        }
    }
});

控制器是:

function MyCtrl($scope, $timeout) {
    $scope.foo = 'ahha';
    $timeout(function () { 
        $scope.foo = "good";
    }, 1000);
}

输出是:

(index):45 ahha
(index):46 NaN
(index):47 NaN
(index):45 ahha
(index):46 boorb
(index):47 boorb
(index):53 val is now ahha
(index):53 val is now good
(index):45 good
(index):46 boorb
(index):47 boorb

controller.$viewValue 最初不是foo 变量的值。此外,controller.$setViewValue("boorb") 根本没有影响scope.ngModel,更新也没有反映在 HTML 中。因此,scope.ngModelcontroller.$viewValue 之间似乎没有关系。似乎对于我想做的任何事情,我都会使用scope.ngModel,并观察这些值。使用controller.$viewValuecontroller.$modelValue 或使用scope.ngModel 让它们保持最新有什么意义?

【问题讨论】:

标签: javascript angularjs angularjs-directive angular-ngmodel


【解决方案1】:

scope: { ngModel: '=' }, 为指令创建了一个隔离作用域,这意味着指令中对foo 的更改将不再反映在MyCtrl 的父作用域中。

此外,$setViewValue() 所做的更改在调用 controller.$render() 之前不会反映在 DOM 中,这会告诉 Angular 在下一个摘要周期中更新 DOM。

但要回答这个问题,NgModelController 及其方法只有在您需要创建一些额外的特殊定制花式数据绑定指令时才真正需要。对于正常的数据输入和验证,您永远不需要使用它。来自the documentation(强调我的):

[NgModelController] 包含用于数据绑定、验证、CSS 更新以及值格式化和解析的服务。它故意不包含任何处理 DOM 渲染或侦听 DOM 事件的逻辑。这种与 DOM 相关的逻辑应该由其他指令提供,这些指令利用 NgModelController 将数据绑定到控制元素。 Angular 为大多数输入元素提供这种 DOM 逻辑

【讨论】:

    【解决方案2】:

    这里的混乱来自于将指令粘贴到现有指令上,即ngInput

    相反,考虑一个新的指令:

    <my-directive ng-model="ugh">Sup</my-directive>
    

    与:

      $rootScope.ugh = 40;
    

    还有:

    .directive('myDirective', function () {
      return {
        require: "ngModel", 
    
        // element-only directive
        restrict: "E", 
    
        // template turns the directive into one input tag
        // 'inner' is on the scope of the *directive*
        template: "<input type='text' ng-model='inner'/>",       
    
        // the directive will have its own isolated scope
        scope: { }, 
    
        link: function (scope, element, attrs, ngModelCtrl) {
          // formatter goes from modelValue (i.e. $rootScope.ugh) to 
          // view value (in this case, the string of twice the model
          // value + '-'
          ngModelCtrl.$formatters.push(function (modelValue) {
            return ('' + (modelValue * 2)) + '-';
          });
    
          // render does what is necessary to display the view value
          // in this case, sets the scope.inner so that the inner
          // <input> can render it
          ngModelCtrl.$render = function () {
            scope.inner = ngModelCtrl.$viewValue;
          };
    
          // changes on the inner should trigger changes in the view value
          scope.$watch('inner', function (newValue) {
            ngModelCtrl.$setViewValue(newValue);
          });
    
          // when the view value changes, it gets parsed back into a model
          // value via the parsers, which then sets the $modelValue, which
          // then sets the underlying model ($rootScope.ugh)
          ngModelCtrl.$parsers.push(function (viewValue) {
            var sub = viewValue.substr(0, viewValue.length-1);
            return parseInt(sub)/2;
          });
        }
      };
    })
    

    试试Plunker

    注意typeof ugh 保持"number",即使指令的视图值是不同的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-01
      • 1970-01-01
      • 2016-12-22
      相关资源
      最近更新 更多