Angularjs:'控制器作为语法'和$ watch

Mir*_*ron 153 javascript angularjs angularjs-scope ng-controller

使用controller as语法时如何订阅属性更改?

controller('TestCtrl', function ($scope) {
  this.name = 'Max';
  this.changeName = function () {
    this.name = new Date();
  }
  // not working       
  $scope.$watch("name",function(value){
    console.log(value)
  });
});
Run Code Online (Sandbox Code Playgroud)
<div ng-controller="TestCtrl as test">
  <input type="text" ng-model="test.name" />
  <a ng-click="test.changeName()" href="#">Change Name</a>
</div>  
Run Code Online (Sandbox Code Playgroud)

Roy*_*loh 159

只需绑定相关的上下文.

$scope.$watch(angular.bind(this, function () {
  return this.name;
}), function (newVal) {
  console.log('Name changed to ' + newVal);
});
Run Code Online (Sandbox Code Playgroud)

示例:http://jsbin.com/yinadoce/1/edit

更新:

Bogdan Gersak的回答实际上是等同的,两个答案都尝试this用正确的语境绑定.但是,我发现他的答案更清晰.

说到这一点,首先,你必须了解它背后的基本思想.

更新2:

对于那些使用ES6的人来说,通过使用arrow function你可以得到一个具有正确上下文OOTB的函数.

$scope.$watch(() => this.name, function (newVal) {
  console.log('Name changed to ' + newVal);
});
Run Code Online (Sandbox Code Playgroud)

  • 我们可以在没有$ scope的情况下使用它来避免混合使用这个和$ scope吗? (9认同)
  • 不,我知道,但它完全没问题.`$ scope`对你来说是一种提供这些方法的服务. (4认同)
  • @Jannik,`angular.bind`返回一个带有有界上下文的函数(arg#1).在我们的例子中,我们将`this`(它是控制器的实例)绑定到函数(arg#2),因此`this.name`表示控制器实例的属性`name`. (3认同)

Nic*_*oli 138

我经常这样做:

controller('TestCtrl', function ($scope) {
    var self = this;

    this.name = 'Max';
    this.changeName = function () {
        this.name = new Date();
   }

   $scope.$watch(function () {
       return self.name;
   },function(value){
        console.log(value)
   });
});
Run Code Online (Sandbox Code Playgroud)

  • 我同意这是最好的答案,但我要补充说,对此的困惑可能是将函数作为`$ scope.$ watch`中的第一个参数传递,并使用该函数从闭包中返回一个值.我还没有遇到另一个这样的例子,但它有效并且是最好的.我没有选择下面的答案的原因(即`$ scope.$ watch('test.name',function(value){});`)是因为它要求我硬编码我命名为我的控制器在我的模板或ui.router的$ stateProvider中,任何更改都会无意中破坏观察者. (3认同)

Art*_*ich 23

您可以使用:

   $scope.$watch("test.name",function(value){
        console.log(value)
   });
Run Code Online (Sandbox Code Playgroud)

这是JSFiddle和你的例子.

  • 这种方法的问题在于JS现在依赖于HTML,迫使控制器在任何地方绑定为相同的名称(在本例中为"test"),以便$ watch工作.很容易引入微妙的错误. (25认同)

小智 13

与使用"TestCtrl as test"中的"test"类似,如另一个答案中所述,您可以为您的范围指定"self":

controller('TestCtrl', function($scope){
    var self = this;
    $scope.self = self;

    self.name = 'max';
    self.changeName = function(){
            self.name = new Date();
        }

    $scope.$watch("self.name",function(value){
            console.log(value)
        });
})
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您不依赖于DOM中指定的名称("TestCtrl as test"),也避免了.bind(this)对函数的需要.

...用于指定的原始html:

<div ng-controller="TestCtrl as test">
    <input type="text" ng-model="test.name" />
    <a ng-click="test.changeName()" href="#">Change Name</a>
</div>
Run Code Online (Sandbox Code Playgroud)


Nie*_*eek 12

AngularJs 1.5支持ControllerAs结构的默认$ ctrl.

$scope.$watch("$ctrl.name", (value) => {
    console.log(value)
});
Run Code Online (Sandbox Code Playgroud)