你的位置:首页 > Java教程

[Java教程]在AngularJS中使用ES6


 

本篇记录一些AngularJS结合使用ES6的各种写法。

ES6中module的导出导入

 

class MainController {  constructor(searchService){    this.searchService = searchService;  }    search(){    this.searchService      .fetch(this.searchTerm)      .then(response => {        this.items = resposne.data.items;      })  }}export {MainController}

 

如何把module中的Controller注册进module呢?

 

import {MainController } from './MainController';import {searchService } from './SeachService';angualr  .module('app',[])  .controller('mainController', MainController)  .service('searchService', searchService);

 

ES6中的继承

 

class PageController{  constructor(name){    this.name = name;  }    sayHello(){    return 'Hello ' + this.name;  }}export {PageController}

 


在另外一个文件中:

 

import {PageController} from './PageController';class ProductPageController extends PageController {  constructor(){    super('jack');  }}export {ProductPageController}

 

最后注册到module中去:

 

angular  .module('app',[])  .controller('ProductPageController', ProductPageController);

 

ES6中Service和Controller的写法

 

class UserService{  constructor($http){    this.$http = $http;  }    getFullName(){    return this.$http.get('api/user/details');  }}class MyController{  //注意:定义时的class名是UserService,正真的名称是在service('realname',UserServie)中定义的  constructor(userService){    userService.getFullName().then(result => this.userName = result.fullName);  }}angular.module('app')  .service('userService', UserService)  .controller('MyController', MyController);

 

ES6中Providers的写法

 

class MyProvider{  constructor(){    this.apiPath = 'default/api';  }  setApiPath(value){    this.apiPath = value;  }  $get($http){    return {      getThings: () => $http.get(this.apiPath);    }  }}

 

ES6的Provider中依赖的注入是写在$get()中的,不能在constructor中注入。Provider中必须有$get()方法。

 


ES6中Factory的写法

 

class Thing{  constructor(){    console.log('create the thing');    showMsg();  }  showMsg(){    console.log('some msg');  }}class ThingFactory{  constructor($timeout){    this.$timeout = $timeout;  }    createThing(){    return this.$timeout(() => new Thing(),1000);  }}

 

如何往module中注册呢?


● 第一种写法

 

angular.module('app')  .factory('thingFactory', () => new ThingFactory());

 

以上写法是错误的,因为$timeout还没有注入进去。可以这样写。

 

angular.module('app')  .factory('thingFactory', ['$timeout', ($timeout) => new ThingFactory($timeout)]);

 

● 第二种写法

但,以上的写法也不是最理想的。最好是写在类中。

 

class ThingFactory{  constructor($timeout){    this.$timeout = $timeout;  }    createThing(){    return this.$timeout(() => new Thing(),1000);  }}ThingFactory.$inject = ['$timeout'];

 

然后,

 

angular.module('app')  .factory('thingFactory', () => new ThingFactory());

 

   
● 第三种写法

 

class ThingFactory{  constructor($timeout){    this.$timeout = $timeout;  }    createThing(){    return this.$timeout(() => new Thing(),1000);  }}ThingFactory.$inject = ['$timeout'];var constructorFn = ThingFactory;//args = ['$timeout']var args = constructorFn.$inject;//根据参数创建ThingFactory实例,任意多的参数var factoryFunction = (...args) => {  return new constructorFn(...args);}//['$timeout', ($timeout) => new ThingFactory($timeout)]var factoryArray = args.push(factoryFunction);angular.module('app')  .factory('thingFactory', factoryArray);

 

ES6中Directive的写法

 

class MyDirective{  constructor($interval){    this.template = '<div>I\'m a directive</div>';    this.restrict = 'E';    this.scope = {};    this.$interval = $interval;  }    compile(tElement){    tElement.css('position','absolute');  }    link(scope, element){    this.$interval(() => this.move(element),1000);  }    move(element){    element.css('left', (Math.random() * 500) + 'px');    element.css('top', (Math.random() * 500) + 'px');  }}

 

以上,如果同时使用compile和link方法,link方法应该是compile的返回值。

 

compile(tElement){  tElement.css('position','absolute');  return this.link;}

 

以上,当angular调用this.link方法,将不会在MyDirective的当前上下文中,调用this.$interval(() => this.move(element),1000);会报undefined类型错误。

如果改成这样:

 

compile(tElement){  tElement.css('position','absolute');  return (scope, element) => {    this.$interval(() => this.move(element),1000);  };}

 

这里,当使用=>后,调用this.$interval(() => this.move(element),1000);方法能保证还MyDirective所在的当前上下文中。

还可以这么写:

 

compile(tElement){  tElement.css('position','absolute');  return this.link.bind(this);}link(scope, element){  this.$interval(() => this.move(element),1000);}

 

但, 以上所有的做法都必须调用compile方法,而在实际场景中,调用compile方法不是必须的。最好这样写:

 

var constructorFn = MyDirective;//是否有compile方法if (!constructorFn.prototype.compile) {  // 如果没有,通过原型创建compile方法  constructorFn.prototype.compile = () => {};}var originalCompileFn = _cloneFunction(constructorFn.prototype.compile);//重写compile方法_override(constructorFn.prototype, 'compile', function () {  return function () {      //先调用原先的compile方法    originalCompileFn.apply(this, arguments);    //如果Directive包含link方法再执行link方法,绑定正确的上下文    if (constructorFn.prototype.link) {      return constructorFn.prototype.link.bind(this);    }  };});

 

往module注册controller、factory、provider等的帮助方法

Michael Bromley还专门写了一个帮助方法,在这里。

大致这样使用:

 

class MyAngularComponent {  /*@ngInject*/  constructor(dependency1, dependency2) {    this.dependency1 = dependency1;    // stuff happens here  }  someMethods() {    this.dependency1.doThatThing();    // more stuff here  }}register('app')  .controller('MyController', MyAngularComponent)  .service('myService', MyAngularComponent)  .provider('myOtherService', MyAngularComponent)  .factory('myFactory', MyAngularComponent)  .directive('myDirective', MyAngularComponent);

 

参考资料:
http://blog.thoughtram.io/angularjs/es6/2015/01/23/exploring-angular-1.3-using-es6.html
http://www.michaelbromley.co.uk/blog/350/exploring-es6-classes-in-angularjs-1-x
https://github.com/timroes/angular-es6-sample