除非是数组,否则可变表不会触发

时间:2016-04-24 20:02:38

标签: angularjs

我有以下标记:

<div ng-controller="DataController as vm">
  <div ng-repeat="name in vm.users track by $index">
    {{name}}
  </div>
  <form name="form" validation="vm.errors">
    <input validator ng-model="vm.name" name="vm.name" placeholder="name" type="text" />
    <a href="#" ng-click="vm.add(vm.name)">Add</a>
  </form>
</div>

我有以下控制器:

function DataController($scope) {
  var vm = this;
  vm.name = "Mary";
  vm.users = ["Alice", "Peter"];
  vm.errors = 1;
  vm.add = function(name) {  
    vm.errors++;
    vm.users.push(name);    
  }  
}

每次添加用户时,我都会增加错误值。

我需要在指令中观察这个变量,所以我有:

app.directive("validation", validation);

function validation() {

  var validation = {
    controller: ["$scope", controller],
    restrict: "A",
    scope: {
     validation: "="
    }
  };

  return validation;

  function controller($scope) {
    this.errors = $scope.validation;
  } 
}  

app.directive("validator", validator);

function validator() {

  var validator = {
    link: link,
    replace: false,
    require: "^validation",
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes, controller) {
    scope.$watch(function() {
     return controller.errors;
   }, function () {
     console.log(controller.errors);
  });
}

console.log显示初始值但不显示新值:
https://jsfiddle.net/qb8o006h/2/

如果我将vm.errors更改为数组,添加值,并观察其长度,那么它工作正常: https://jsfiddle.net/nprx63qa/2/

为什么我的第一个例子不起作用?

2 个答案:

答案 0 :(得分:1)

validation指令controller中的两个示例中,您为errors属性分配了对$scope.validation值的引用。

在第一个示例中,值为数字,因此不可变 - 1 - 无法修改参考值。 vm.add修改控制器实例的属性值。然后,更改将传播到validation指令$scope.validation,但传播到validation指令控制器实例$errors属性。

在第二个示例中,值是一个数组,因此可变 - [] - 可以修改参考值。 vm.add 修改控制器实例的属性值。因此,validation指令控制器实例errors属性值是完全相同的Array实例 - 因此它会length更改。

使用不可变值的一种方法(如第一个示例中所示)是$watch控制器函数,如this example中所示:

function link(scope, element, attributes, controller) {
  scope.$watch(controller.errors, function (newValue) {
    console.log(newValue);
  });
}

controller.errors的定义如下:

function controller($scope) {
  this.errors = function(){ return $scope.validation; };
}

您可以找到以下有用的答案:

答案 1 :(得分:1)

我更新你的代码,你可以访问更新的属性scope.vm.errors,如果你调试代码,你会看到属性controller.errors没有更新(每次摘要后所有的手表都被调用)重新评估他们)。如果从范围访问属性错误,可以添加$ scope。$ watch并使其工作。但是我不建议在指令中使用$ scope。$ watch。但那取决于你:

    var app = angular.module('app', []);

app.controller("DataController", DataController);

function DataController($scope) {

    var vm = this;
  vm.name = "Mary";
  vm.users = ["Alice", "Peter"];
  vm.errors = 1;
  vm.add = function(name) {  
      vm.errors++;
      vm.users.push(name);    
  }

}

app.directive("validation", validation);

function validation() {

  var validation = {
    controller: ["$scope", controller],
    restrict: "A",
    scope: {
      validation: "="
    }
  };

  return validation;

  function controller($scope) {
    this.errors = $scope.validation;
  } 

}  

app.directive("validator", validator);

function validator() {

  var validator = {
    link: link,
    replace: false,
    require: "^validation",
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes, controller) {
    scope.$watch(function() {
                return scope.vm.errors
    }, function () {
      console.log(scope.vm.errors);
    });
  }

}

https://jsfiddle.net/kcvqn5kL/