在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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM