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