6

我试图用一些对谷歌,风格指南站点定义angulars最佳实践:https://google-styleguide.googlecode.com/svn/trunk/angularjs-google-style.htmlAngularJS最佳实践 - 风格指南

但此刻我的一些问题苦苦挣扎。在我使用这个样式指南之前,我有$scope变量可用于在变量上执行$watch

app.controller('myController',['$scope', function($scope) { 
    $scope.$watch('myVariable', function(val) { 
     alert("I'm changed"); 
    }); 
}]); 

现在用我的新方法,我不知道如何处理这个?我还应该注入$scope?因为我不使用$watch时不需要注入$scope

function myController($scope) { 
    var vm = this; 

    vm.myVariable = "aVariable"; 
    vm.$watch('vm.myVariable', function(val) { 
     // error because $watch is undefined 
    }); 

    //$scope.$watch - works 
} 

app.controller('myController',['$scope', myController]); 

styleguide还建议使用原型。但是如果我不得不注入服务呢?在原型中使用服务的最佳方法是什么?

function myController(MyService) { 
    var vm = this; 

    vm.myService = MyService; 
} 

myController.prototype.callService = function() { 
    var vm = this; 

    vm.myService.doSomething(); 
} 

这是正确的吗?或者我错过了什么,有没有一个地方可以找到更多关于这种角度编程风格的信息?

在我看来,它感觉更像自然的JavaScript,我想用这种方式来组织我的AngularJS应用程序。

在此先感谢

更新

对于 '服务' 的问题,我想的东西如下:

function MyBaseController(AService, BService, CService) { 
    this.aService = AService; 
    this.bService = BService; 
    this.cService = CService; 
} 

function myController() { 
    var vm = this; 
    MyBaseController.apply(vm, arguments); 
} 

myController.prototype.doSomething() { 
    var vm = this; 
    this.aService.somethingElse(); 
} 

但是,这感觉不对IMO ..

+0

伟大的问题!对于你关于$ watch的问题,我想知道风格指南是否试图避免在控制器中调用$ watch,因为他们声明“控制器是类”。既然你知道数据在控制器中的变化,当控制器内部调用一个特定的方法时,是否会执行“$ watch”? – Pete

+0

其实我想对一个指令内部变化的变量执行'$ watch'。我认为在方法内改变一个变量时不会有问题。我们称之为范围,无论如何都会得到更新。 – Dieterg

+1

在指令中,您可以从链接,编译和控制器访问范围,因此在这些情况下可以访问$ watch。 – Pete

回答

7

注入$ scope来访问像$ watch这样的东西是完全有效的,即使在使用“controller as”时也是如此ntax。例如:

JS

var MyController = function($scope) { 
    $scope.$watch('ctrl.someVar' function() { 
     ... 
    }); 

    this.someVar = 123; 
} 

MyController.$inject = ['$scope']; 

HTML

<div ng-controller="MyController as ctrl"> 
    .... 
</div> 

你给到控制器是好的注射服务的第一个例子。对于继承的例子,我会做这样的事情。

var BaseController = function(AService, BService) { 
    this.aService = AService; 
    this.bService = BService; 
} 

BaseController.prototype.doSomethingWithAAndB = function() { 
    ... 
} 

var MyController = function(AService, BService, CService) { 
    BaseController.call(this, AService, BService); 

    this.cService = CService; 
} 

MyController.$inject = ['AService', 'BService', 'CService']; 

//Note: you'll need to add a polyfill for Object.create if you want to support ES3. 
MyController.prototype = Object.create(BaseController.prototype); 

如果你觉得太麻烦了指定子控制器的所有参数,你总是可以只注入$injector并传递到你的基本控制器。

+0

重申您的继承示例,可能值得设置原型构造函数以及'MyControlleer.prototype.constructor = MyController'。见http://stackoverflow.com/questions/8453887/why-is-it-necessary-to-set-the-prototype-constructor/8454111#8454111 – Beyers

1

@rob答案是正确的。有完全有效的理由仍然希望$scope注入您的控制器,$watch$on$emit$broadcast仅举几例。当然,在某些情况下,您可以使用指令或服务避开此要求,但这并不总是值得花时间或复杂性。

我已经给出了controller as语法,但发现在我的大部分使用情况下,我的控制器仍然依赖于$scope。我不喜欢这个,所以我最终采用了以下惯例:

var MyController = function($scope) { 
    $scope.vm = {}; 
    var vm = $scope.vm; 

    vm.propA = 1; 
    vm.propB = 2; 
    vm.funcA = function(){}; 

    $scope.$watch('vm.propA' function() { 
    }); 
} 

因此,它采用'旧学校'的方法,但有一个新的学校的感觉。视图中的所有内容都挂起了vm