2017-09-01 23 views
0

角度1.6.xおよびTypescriptのWebpackを使用していて、角度付きDIを使用してES6のインポートを中止しました。それがベストプラクティスかを遵守していた場合、私は知らないAngularJS - 角度付きDIシステムの代わりにES6インポートを使用

// inject.ts 
    import * as angular from 'angular'; 

    export function inject (...params: string[]) { 

     function doCall (param: string, klass: Function) { 
      const injector = angular.injector([ 'ng' ]); 
      const service = injector.get(param); 
      try { 
       klass.prototype[ param ] = service; 
      } catch (e) { 
       window.console.warn(e); 
      } 
     } 

     // tslint:disable-next-line:ban-types 
     return function (klass: Function) { 
      params.forEach((param) => { 
       doCall(param, klass); 
      }); 
     }; 
    } 

// posts.service.ts 
import { inject } from './inject'; 
import { IPost, Post } from './post'; 

@inject('$http') 
export class PostsService { 
    public $http: angular.IHttpService; 
    get(): Promise<IPost[]> { 
     const posts: IPost[] = []; 
     const promise = new Promise<IPost[]>((resolve, reject) => { 
      this.$http.get<IPost[]>('https://jsonplaceholder.typicode.com/posts') 
      .then((response) => { 
       response.data.forEach(item => { 
        posts.push(new Post(item)); 
       }); 

       resolve(posts); 
      }); 
     }); 

     return promise; 
    } 
} 


// post.ts 
export interface IPost { 
    userId: number; 
    id: number; 
    title: string; 
    body: string; 
} 
export class Post implements IPost { 
    userId: number; 
    id: number; 
    title: string; 
    body: string; 

    constructor (item: IPost) { 
     this.userId = item.userId; 
     this.id = item.id; 
     this.title = item.title; 
     this.body = item.body; 
    } 
} 


// controller.ts 
import { IPost } from './post'; 
import { PostsService } from './posts.service'; 

export class Controller { 
    public postService: PostsService; 
    public posts: IPost[]; 
    constructor (private $scope: angular.IScope) { 
     this.postService = new PostsService(); 
    } 

    $onInit() { 
     this.postService.get() 
     .then((posts) => { 
      this.posts = posts; 
      this.$scope.$digest(); 
     }); 
    } 
} 

// index.ts 
import * as angular from 'angular'; 

import { Controller } from './app/controller'; 

import './index.scss'; 

export const app: string = 'app'; 

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


angular.bootstrap(document.body, [app]); 

、しかし:私は$http$resourceなどのようないくつかのNG機能を必要とするとき、私は彼らが直接このように、デコレータによってangular.injector機能を使用して注入しますそれは今のところきれいに働いています。

このアプローチを使用すると問題(パフォーマンス、悪い習慣など)はありますか?

+0

角度モジュール/ DIモジュールとES6モジュールがお互いを補完します。それらは交換できません。 * angular.injector *を直接使用する - それはひどく間違っていますが、あなたが期待したことをしないので、これまで 'angular.injector'を使用することはめったにありません。 – estus

+0

私はこれが良い質問だと思っていますが、書いたところではここから外れています。あなたは完全に機能しているコードを持っています。これは、最初の赤旗です。「私はあなたの考えを聞いています」というステートメントは、[dont-ask](https://stackoverflow.com)でほぼ直接引用されています。/help/dont-ask)。私は質問にメリットがあると思いますが、ディスカッション・ピースではなく、QAのために、このテクニックの要点や要点についてもっと詳しく説明することを検討したいと思うかもしれません。 – Claies

答えて

2

ESモジュールは、角度モジュールとDIを置き換えることはできません。彼らはお互いを補完し、アプリケーションをモジュール化してテスト可能に保ちます。

ES6モジュールは、コントローラ/サービスのサブクラス化(AngularモジュールとDIだけではよく見えないものなど)のような拡張可能な層を提供します。

ES6または活字体で推奨されるアプローチは、$injectアノテーションで、従来DIを行うことです。

export class PostsService { 
    static $inject = ['$http']; 
    constructor(
    public $http: angular.IHttpService 
) {} 
    ... 
} 

それは、ファイルごとにアプリケーションは、モジュラーおよびテスト可能なまま、このように一つのモジュールを持つことも良い方法だ:

export default angular.module('app.posts', []) 
    .service('posts', `PostsService) 
    .name;` 

そのdefault輸出は、直接に依存して別のモジュールにインポートすることができ、モジュール名です:

import postsModule from '...'; 
... 
export default angular.module('app.controller', [postsModule]) 
    .controller('controller', Controller) 
    .name;` 

通常、アプリケーションインジェクタはデコレータから到達できません。たとえそれが実稼働環境で動作するようにハックをかけることができたとしても、テストではうんざりになります。

angular.injectorは、新しいインジェクタ(すなわち、アプリケーションインスタンス)を作成し、生産に非常に限られた適切な用途があります:

angular.injector(['ng']).get('$rootScope') !== angular.injector(['ng']).get('$rootScope'); 

開発者が現在の$injectorインスタンスを取得する方法を知らない場合には、しばしば誤用されます。このような場合には使用しないでください。

+0

ありがとうございます。私はあなたがここに投稿したこのアプローチについて知っていましたが、angle.injectorを使用してデコレータを使って角度private関数を使用するというこのアイデアを思いつき、それが良いかどうかわかりませんでした。私は今、角度のあるDIに固執すると思います。 – darksoulsong

+0

そこに行って、それをしました。いいえ、それは確かに良い習慣ではありません。理論的には、ブートストラッピング中にインジェクタを公開してデコレータで使用することは可能ですが、一度に複数のインジェクタが存在する可能性があるため、状況が壊れる可能性があります。答えに表示されるスタイルは、一般にTypeScriptにとって望ましいものです(ES6では異なる場合があります)。 – estus

関連する問題