export default class ServiceA {}serviceB的實現,service/b.js
export default class ServiceB {}moduleA的殼子定義,moduleA.js
import ServiceA from './services/a'; import ServiceB from './services/b'; export default angular.module('moduleA'[]) .service('ServiceA', ServiceA) .service('ServiceB', ServiceB) .name;存在一個moduleB要使用moduleA:
import moduleA from './moduleA'; export default angular.module('moduleB', [moduleA]).name;
<div ng-controller="AppCtrl as app"> <div ng-bing="app.name"></div> <button ng-click="app.getName">get app name</button> </div>controller AppCtrl.js
export default class AppCtrl { constructor() { this.name = 'angualr$es6'; } getName() { return this.name; } }module
import AppCtrl from './AppCtrl'; export default angular.module('app', []) .controller('AppCtrl', AppCtrl) .name;
export default class DirectiveA {}DDO上面的東西大體能夠分爲兩類,屬性和方法,因此就在構造函數裏這樣定義:
constructor() { this.template = template; this.restrict = 'E'; }接下來就是controller和link,compile等函數了,好比controller,能夠實現一個普通的controller類,而後賦值到controller屬性上來:
this.controller = ControllerA;寫directive的時候,儘可能使用controllerAs這樣的語法,這樣controller能夠清晰一些,沒必要注入$scope,並且還可使用bingToController屬性,把在指令attr上定義的值或方法傳遞到controller實例上來。接下來咱們使用三種方法來定義指令
import template from '../template/calendar.html'; import CalendarCtrl from '../controllers/calendar'; import '../css/calendar.css'; export default class CalendarDirective{ constructor() { this.template = template; this.restrict = 'E'; this.controller = CalendarCtrl; this.controllerAs = 'calendarCtrl'; this.bingToController = true; this.scope = { minDate: '=', maxDate: '=', selecteDate: '=', dateClick: '&' }; } link(scope) { //這個地方引入了scope,應儘可能避免這種作法, //可是搬到controller寫成setter,又會在constructor以前執行 scope.$watch('calendarCtrl.selecteDate', newDate => { if(newDate) { scope.calendarCtrl.calendar.year = newDate.getFullYear(); scope.calendarCtrl.calendar.month = newDate.getMonth(); scope.calendarCtrl.calendar.date = newDate.getDate(); } }); } }而後在module定義的地方:
import CalendarDirective from './directives/calendar'; export default angular.module('components.form.calendar', []) .directive('snCalendar', () => new CalendarDirective()) .name;
// DatePickerCtrl.js export default class DatePickerCtrl { $onInit() { this.date = `${this.year}-${this.month}`; } getMonth() { ... } getYear() { ... } }注意,這裏先寫了controller而不是link/compile方法,緣由在於一個數據驅動的組件體系下,咱們應該儘可能減小對DOM操做,所以理想狀態下,組件是不須要link或compile方法的,並且controller在語義上更貼合mvvm架構。
import template from './date-picker-tpl.html'; import controller from './DatePickerCtrl'; const ddo = { restrict: 'E', template, //es6對象簡寫 controller, controllerAs: '$ctrl', bingToController: { year: '=', month: '=' } }; export default angular.module('components.datePicker', []) .directive('dataPicker', ddo) .name;在整個系統設計中只有index.js(定義模塊的地方)是框架可識別的,其它地方的業務邏輯都不該該出現框架的影子,這樣方便移植。
//DirectiveController.js export class DirectiveController { $onInit() { } $onChanges(changesObj) { } $onDestroy() { } $postLink() { } } //index.js import template from './date-picker-tpl.html'; import controller from './DatePickerCtrl'; const ddo = { template, controller, bindings: { year: '<', month: '<' } }; export default angular.module('components.datepicker', []) .component('datePicker', ddo) .name;
export default class ServiceA {}serviceA的模塊包裝器moduleA的實現
import ServiceA from './service/a'; export angular.module('moduleA', []) .service('ServiceA', ServiceA) .name;
import EntityA from './model/a'; export default function FactoryA { return new EntityA(); }factoryA的模塊包裝器moduleA的實現
import FactoryA from './factory/a'; export angular.module('modeuleA', []) .factory('FactoryA', FactoryA) .name;
export default class ControllerA { constructor(ServiceA) { this.serviceA = ServiceA; } } ControllerA.$inject = ['ServiceA'];
import ControllerA from './controllers/a'; export angular.module('moduleA', []) .controller('ControllerA', ControllerA);
export const VERSION = '1.0.0';
import { dateFormatter } './transformers'; export default class Controller { constructor() { this.data = [1,2,3,4]; this.currency = this.data .filter(v => v < 4) .map(v => '$' + v); this.date = Date.now(); this.today = dateFormatter(this.date); } }
<div ng-controller="TestCtrl as testCtrl"> <input ng-model="testCtrl.aaa"> </div>
xxx.controller("TestCtrl", [function() { this.aaa = 1; }]);實際上框架會作一些事情:
$scope.testCtrl = new TestCtrl();對於這一塊,把那個function換成ES6的類就能夠了。
$scope.$watch("a", function(val) { $scope.b = val + 1; });咱們能夠直接使用ES5的setter和getter來定義就能夠了。
class A { set a(val) { //a改變b就跟着改變 this.b = val + 1; } }若是有多個變量要觀察,例如
$scope.$watchGroup(["firstName", "lastName"], function(val) { $scope.fullName = val.join(","); });咱們能夠這樣寫
class Controller { get fullName() { return `${this.firstName} ${this.lastName}`; } }
<input type="text" ng-model="$ctrl.firstName"> <input type="text" ng-model="$ctrl.lastName"> <span ng-bind="$ctrl.fullName"></span>
在$scope上,另一套經常使用的東西是$emit,$broadcast,$on,這些API實際上是有爭議的,由於若是說作組件的事件傳遞,應當以組件爲單位進行通訊,而不是在另一套體系中。因此咱們也能夠不用它,比較直接的東西經過directive的attr來傳遞,更廣泛的東西用全局的相似Flux的派發機制去通訊。javascript
根做用域的問題也是同樣,儘可能不要去使用它,對於一個應用中全局存在的東西,咱們有各類策略去處理,沒必要糾結於$rootScope。css