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