24
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

僕なりの AngularJS + TypeScript のお作法ベスト?プラクティス ~ カスタムディレクティブ編

Last updated at Posted at 2015-08-13

念の為前書きですが、今回の題材は、私が調べてもベストプラクティスが見つからなかった部分を題材にしておりますので、
もしもっと良い方法があった場合ご教示いただければ、という前提で書かせていただきます。

解決したいこと(困りごと)

  1. カスタムディレクティブの可読性が悪い
  2. TypeScriptでのベストプラクティスの例が少ない(or 無い)
  3. classとか有効活用したい

まず...

困り気味なソースを見てみましょう。

angular.module('fooApp')
  .directive('fooDirective', function () {
    return: {
      restrict: 'E',
      link: function ($scope, $element, $attrs) {
        $scope.foo = 'foo';
        $scope.bar = 'bar';

        xxxx = () => {
          console.log($scope.foo, $scope.bar);
        };

        $element.on('click', function () {
          xxxx($scope.foo, $scope.bar);
        });
      }
    }
  })
;

上記の場合、ディレクティブが増えれば増えるほど、
複雑な処理をすればするほど可読性が悪くなってきます。
あといちいち「$scope」とか書くのめんどうくさい!

つぎに...

改善したソースを見てみましょう。

class FooDirective {
  restrict: string = 'E';
  controller: string = 'FooCtrl as c'
}
class FooController {
  public foo: string = 'foo';
  public bar: string = 'bar';

  // 個人的なポリシーとしてjQueryオブジェクト以外に
  // $を付けたくないので、別の名前のメンバ変数を用意しています
  scope: ng.IScope;
  attrs: any;

  constructor (
    private $element: ng.IAugmentedJQuery,
    $scope: ng.IScope,
    $attrs: any
  ) {
    this.scope = $scope;
    this.attrs = $attrs;

    this.bindEvents();
  }

  bindEvents () : void {
    this.$element.on('click', () => {
      this.xxxx();
    });
  }

  xxxx () : void {
    console.log(this.foo + this.bar);
  }
}

angular.module('fooApp')
  .controller('fooCtrl', FooController)
  .directive('fooDirective', () => new FooDirective())
;

ディレクティブ用のコントローラーをクラスとして明記しています。
もちろん、クラスを使っているので、継承も自由にできます。
似たようなディレクティブだけど、少し性質を変えたい時とかこの書き方だと大分いい!

ディレクティブを定義している部分を見れば、どのコントローラーと対になっているかもわかるので、
私としては一番よかった書き方になります。

「Controller as」の有効利用

AngularJS + TypeScriptでは、「Controller as」を使う、というお作法があります。
これはカスタムディレクティブでも有効で、
クラス内でのthisが$scopeに相当するため、可読性の向上の助けになるかと思います。

$scope.fn = () => {
  // ...
};

とか書いていたものは

public fn () : void {
  // ...
}

と、なんか素敵に書く事ができます。

最後に

私自身まだまだこの構成でプロダクトを作りはじめたばかりのため、
100%信じていただくより、いち参考資料として見ていただければ幸いです。

今後コントローラーではなくディレクティブをたくさん使ってねー
みたいな仕様になりそうなので、いそいそと書かせていただきました。

ありがとうございました!

24
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?