Angularjs:'controller as syntax'和$ watch

当使用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) }); }); 
 <div ng-controller="TestCtrl as test"> <input type="text" ng-model="test.name" /> <a ng-click="test.changeName()" href="#">Change Name</a> </div> 

只要绑定相关的上下文。

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

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

更新:

Bogdan Gersak的答案实际上是相当的,两种答案都尝试将this与正确的上下文结合起来。 但是,我发现他的答案更清洁。

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

更新2:

对于那些使用ES6的人来说,通过使用arrow function你可以得到一个正确的上下文OOTBfunction。

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

我通常这样做:

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

您可以使用:

  $scope.$watch("test.name",function(value){ console.log(value) }); 

这是你的例子JSFiddle的工作。

与使用“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) }); }) 

通过这种方式,您不必绑定在DOM中指定的名称(“TestCtrl as test”),也可以避免将(绑定)这个函数绑定到该函数。

…用于指定的原始html:

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

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

 $scope.$watch("$ctrl.name", (value) => { console.log(value) }); 

这里是你如何做到这一点没有$范围(和$手表!) 五大错误 – 滥用手表

如果使用“controller as”语法,避免使用$ scope会更好,更清晰。

这是我在JSFiddle中的代码。 (我正在使用服务来保存名称,否则ES5 Object.defineProperty的set和get方法会导致无限的调用。

 var app = angular.module('my-module', []); app.factory('testService', function() { var name = 'Max'; var getName = function() { return name; } var setName = function(val) { name = val; } return {getName:getName, setName:setName}; }); 
 app.controller('TestCtrl', function (testService) { var vm = this; vm.changeName = function () { vm.name = new Date(); } Object.defineProperty(this, "name", { enumerable: true, configurable: false, get: function() { return testService.getName(); }, set: function (val) { testService.setName(val); console.log(vm.name); } }); }); 

用ES6语法编写$ watch并不像我想象的那么容易。 以下是你可以做的事情:

 // Assuming // controllerAs: "ctrl" // or // ng-controller="MyCtrl as ctrl" export class MyCtrl { constructor ($scope) { 'ngInject'; this.foo = 10; // Option 1 $scope.$watch('ctrl.foo', this.watchChanges()); // Option 2 $scope.$watch(() => this.foo, this.watchChanges()); } watchChanges() { return (newValue, oldValue) => { console.log('new', newValue); } } } 

你可以传入一个函数作为$ watch()的第一个参数:

  app.controller('TestCtrl', function ($scope) { this.name = 'Max'; // hmmm, a function $scope.$watch(function () {}, function (value){ console.log(value) }); }); 

这意味着我们可以返回我们的this.name引用:

 app.controller('TestCtrl', function ($scope) { this.name = 'Max'; // boom $scope.$watch(angular.bind(this, function () { return this.name; // `this` IS the `this` above!! }), function (value) { console.log(value); }); }); 

阅读关于控制器的一个有趣的职位主题https://toddmotto.com/digging-into-angulars-controller-as-syntax/

:当视图和控制器耦合到路由中或通过指令定义对象时,这不起作用。 下面显示的内容只有在HTML中有“SomeController作为SomeCtrl”时才有效。 就像Mark V.在下面的评论中指出的那样,就像他说的那样,Bogdan做得更好。

我使用: var vm = this; 在控制器的开始,让我不知道“这个”这个词。 然后vm.name = 'Max'; 并在手表我return vm.name 。 我使用“vm”就像@Bogdan使用“自我”。 这个variables,不pipe是“vm”还是“self”,都是需要的,因为单词“this”在函数内部具有不同的上下文。 (所以返回this.name不会工作)是的,你需要注入美元的范围在你的美丽的“控制器为”解决scheme,以达到$手表。 请参阅John Papa的风格指南: https : //github.com/johnpapa/angularjs-styleguide#controllers

 function SomeController($scope, $log) { var vm = this; vm.name = 'Max'; $scope.$watch('vm.name', function(current, original) { $log.info('vm.name was %s', original); $log.info('vm.name is now %s', current); }); }