ng-mtg#6 angularjs ディレクティブ・パターン

84
1 ディレクティブ・パターン

Upload: hayashi-yuichi

Post on 19-Jun-2015

7.698 views

Category:

Technology


0 download

DESCRIPTION

株式会社LIG フロントエンドエンジニア 2014年7月25日にサイバーエージェントで行われたAngularJSの勉強会に登壇したときのスライドです。 http://angularjs-jp.doorkeeper.jp/events/12996

TRANSCRIPT

Page 1: ng-mtg#6 AngularJS ディレクティブ・パターン

1

ディレクティブ・パターン

Page 2: ng-mtg#6 AngularJS ディレクティブ・パターン

2

@frontainerFront-end Engineer

2014/4 LIG入社 フロントエンドエンジニア

プロフィール

http://github.com/frontainer

http://trifort.jp/library/cavy/

現在はWebサイトを作ったりテンプレート作ったりいろいろ

前職ではゲームのフロントエンド開発や canvasライブラリを作って遊んだりしてました。

これまでBackboneで2案件、Angularで5案件実装してきました。

林 優一

Page 3: ng-mtg#6 AngularJS ディレクティブ・パターン

3

@frontainerFront-end Engineer

前回はLIG社内で勉強会を行いました

プロフィール

http://www.slideshare.net/frontainer/angularjs-1angularjs-lig

Page 4: ng-mtg#6 AngularJS ディレクティブ・パターン

4

@frontainerFront-end Engineer

犬が好きです

プロフィール

Page 5: ng-mtg#6 AngularJS ディレクティブ・パターン

5

本題に入る前に質問です

Page 6: ng-mtg#6 AngularJS ディレクティブ・パターン

6

Q. AngularJSを実務で使ったことはありますか?

Page 7: ng-mtg#6 AngularJS ディレクティブ・パターン

7

Q. (チュートリアル以外で)ディレクティブを作ったことはありますか?

Page 8: ng-mtg#6 AngularJS ディレクティブ・パターン

8

今回はそんな「ディレクティブ」について

過去の案件を振り返ってパターン分けしてみました

Page 9: ng-mtg#6 AngularJS ディレクティブ・パターン

実装のパターン

[おまけ]より良いパフォーマンスのために

まとめ

9

呼び出しのパターン

ディレクティブ・パターンとは

Page 10: ng-mtg#6 AngularJS ディレクティブ・パターン

10

ディレクティブ・パターンとは

Page 11: ng-mtg#6 AngularJS ディレクティブ・パターン

11

ディレクティブ・パターンとは

ディレクティブ・パターンとは

一般的に認知されているものではなく勝手に付けた呼称です。

パターン化することで使う場面を想定してもらえるようになれば嬉しいです

ディレクティブをあまり活用したことのない方に少しでもヒントになれば

過去に携わった案件でのディレクティブを振り返ってパターン分けしたもの

Page 12: ng-mtg#6 AngularJS ディレクティブ・パターン

12

呼び出しパターン

Page 13: ng-mtg#6 AngularJS ディレクティブ・パターン

13

呼び出しパターン

angular.module('directives').directive('dummyText',function() { return { restrict: 'ACEM', replace: true, template: '<p class="bg-success">OK</p>' }; });

ディレクティブ名呼び出し方

Page 14: ng-mtg#6 AngularJS ディレクティブ・パターン

14

Attr ibute

Class

Element

Comment

01 Restrict: A

02 Restrict: C

03 Restrict: E

04 Restrict: M

呼び出しパターン

Page 15: ng-mtg#6 AngularJS ディレクティブ・パターン

15

The normalization process is as follows: !

Strip x- and data- from the front of the element/attributes. Convert the :, -, or _-delimited name to camelCase.[引用] https://docs.angularjs.org/guide/directive

呼び出しパターン

Page 16: ng-mtg#6 AngularJS ディレクティブ・パターン

16

通常以下のような処理が行われます: !

ElementやAttributeの前についているx-とdata-は取り除きます。 :、-や_などの区切り文字はキャメルケースへ変換されます。

呼び出しパターン

Page 17: ng-mtg#6 AngularJS ディレクティブ・パターン

17

検証

Page 18: ng-mtg#6 AngularJS ディレクティブ・パターン

18

01 Restrict: A

呼び出しパターン

- Attribute -

Page 19: ng-mtg#6 AngularJS ディレクティブ・パターン

<div dummy-text><p class=“bg-danger">NG</p></div> <div dummy_text><p class=“bg-danger">NG</p></div> <div dummy:text><p class=“bg-danger”>NG</p></div> <div dummyText><p class=“bg-danger">NG</p></div> <div data-dummy-text><p class=“bg-danger">NG</p></div> <div data-dummy_text><p class=“bg-danger">NG</p></div> <div data-dummy:text><p class=“bg-danger”>NG</p></div> <div data-dummyText><p class=“bg-danger">NG</p></div> <div x-dummy-text><p class=“bg-danger">NG</p></div> <div x-dummy_text><p class=“bg-danger">NG</p></div> <div x-dummy:text><p class=“bg-danger">NG</p></div> <div x-dummyText><p class="bg-danger">NG</p></div>

19

いろんな属性で呼び出してみた

呼び出しパターン 01 Restrict: A

Page 20: ng-mtg#6 AngularJS ディレクティブ・パターン

<div dummy-text><p class=“bg-danger">NG</p></div> <div dummy_text><p class=“bg-danger">NG</p></div> <div dummy:text><p class=“bg-danger”>NG</p></div> <div dummyText><p class=“bg-danger">NG</p></div> <div data-dummy-text><p class=“bg-danger">NG</p></div> <div data-dummy_text><p class=“bg-danger">NG</p></div> <div data-dummy:text><p class=“bg-danger”>NG</p></div> <div data-dummyText><p class=“bg-danger">NG</p></div> <div x-dummy-text><p class=“bg-danger">NG</p></div> <div x-dummy_text><p class=“bg-danger">NG</p></div> <div x-dummy:text><p class=“bg-danger">NG</p></div> <div x-dummyText><p class="bg-danger">NG</p></div>

20

結果・・・

呼び出しパターン

camelCaseはダメでした

01 Restrict: A

Page 21: ng-mtg#6 AngularJS ディレクティブ・パターン

21

02 Restrict: C

呼び出しパターン

- Class -

Page 22: ng-mtg#6 AngularJS ディレクティブ・パターン

<div class="dummy-text"><p class=“bg-danger">NG</p></div> <div class="dummy_text"><p class=“bg-danger">NG</p></div> <div class="dummy:text"><p class=“bg-danger">NG</p></div> <div class="dummyText"><p class=“bg-danger">NG</p></div> <div class="data-dummy-text"><p class=“bg-danger">NG</p></div> <div class="data-dummy_text"><p class=“bg-danger">NG</p></div> <div class=“data-dummy:text”><p class=“bg-danger">NG</p></div> <div class="data-dummyText"><p class=“bg-danger">NG</p></div> <div class="x-dummy-text"><p class=“bg-danger">NG</p></div> <div class="x-dummy_text"><p class=“bg-danger">NG</p></div> <div class=“x-dummy:text”><p class=“bg-danger">NG</p></div> <div class="x-dummyText"><p class="bg-danger">NG</p></div>

22

いろんなクラスで呼び出してみた

呼び出しパターン 02 Restrict: C

Page 23: ng-mtg#6 AngularJS ディレクティブ・パターン

23

<div class="dummy-text"><p class=“bg-danger">NG</p></div> <div class="dummy_text"><p class=“bg-danger">NG</p></div> <div class="dummy:text"><p class=“bg-danger">NG</p></div> <div class="dummyText"><p class=“bg-danger">NG</p></div> <div class="data-dummy-text"><p class=“bg-danger">NG</p></div> <div class="data-dummy_text"><p class=“bg-danger">NG</p></div> <div class=“data-dummy:text”><p class=“bg-danger">NG</p></div> <div class="data-dummyText"><p class=“bg-danger">NG</p></div> <div class="x-dummy-text"><p class=“bg-danger">NG</p></div> <div class="x-dummy_text"><p class=“bg-danger">NG</p></div> <div class=“x-dummy:text”><p class=“bg-danger">NG</p></div> <div class="x-dummyText"><p class="bg-danger">NG</p></div>

呼び出しパターン 02 Restrict: C

結果・・・

:はダメでした

Page 24: ng-mtg#6 AngularJS ディレクティブ・パターン

24

03 Restrict: E

呼び出しパターン

- Element -

Page 25: ng-mtg#6 AngularJS ディレクティブ・パターン

<dummy-text><p class=“bg-danger">NG</p></dummy-text> <dummy_text><p class=“bg-danger”>NG</p></dummy_text> <dummy:text><p class=“bg-danger">NG</p></dummy:text> <dummyText><p class=“bg-danger">NG</p></dummyText> <data-dummy-text><p class=“bg-danger">NG</p></data-dummy-text> <data-dummy_text><p class=“bg-danger">NG</p></data-dummy_text> <data-dummy:text><p class=“bg-danger">NG</p></data-dummy:text> <data-dummyText><p class=“bg-danger”>NG</p></data-:dummyText> <x-dummy-text><p class=“bg-danger">NG</p></x-dummy-text> <x-dummy_text><p class=“bg-danger">NG</p></x-dummy_text> <x-dummy:text><p class=“bg-danger">NG</p></x-dummy:text> <x-dummyText><p class=“bg-danger">NG</p></x-dummyText>

25

呼び出しパターン

いろんなタグで呼び出してみた

03 Restrict: E

Page 26: ng-mtg#6 AngularJS ディレクティブ・パターン

<dummy-text><p class=“bg-danger">NG</p></dummy-text> <dummy_text><p class=“bg-danger”>NG</p></dummy_text> <dummy:text><p class=“bg-danger">NG</p></dummy:text> <dummyText><p class=“bg-danger">NG</p></dummyText> <data-dummy-text><p class=“bg-danger">NG</p></data-dummy-text> <data-dummy_text><p class=“bg-danger">NG</p></data-dummy_text> <data-dummy:text><p class=“bg-danger">NG</p></data-dummy:text> <data-dummyText><p class=“bg-danger”>NG</p></data-:dummyText> <x-dummy-text><p class=“bg-danger">NG</p></x-dummy-text> <x-dummy_text><p class=“bg-danger">NG</p></x-dummy_text> <x-dummy:text><p class=“bg-danger">NG</p></x-dummy:text> <x-dummyText><p class=“bg-danger">NG</p></x-dummyText>

26

呼び出しパターン

結果・・・

camelCaseは ダメでした

03 Restrict: E

Page 27: ng-mtg#6 AngularJS ディレクティブ・パターン

27

04 Restrict: M

呼び出しパターン

- Comment -

Page 28: ng-mtg#6 AngularJS ディレクティブ・パターン

<!-- directive: dummy-text —> <!-- directive: dummy_text —> <!-- directive: dummy:text —> <!-- directive: dummyText —> <!-- directive: data-dummy-text —> <!-- directive: data-dummy_text —> <!-- directive: data-dummy:text —> <!-- directive: data-dummyText —> <!-- directive: x-dummy-text —> <!-- directive: x-dummy_text —> <!-- directive: x-dummy:text —> <!-- directive: x-dummyText -->

28

呼び出しパターン

いろんなコメントで呼び出してみた

04 Restrict: M

Page 29: ng-mtg#6 AngularJS ディレクティブ・パターン

<!-- directive: dummy-text —> <!-- directive: dummy_text —> <!-- directive: dummy:text —> <!-- directive: dummyText —> <!-- directive: data-dummy-text —> <!-- directive: data-dummy_text —> <!-- directive: data-dummy:text —> <!-- directive: data-dummyText —> <!-- directive: x-dummy-text —> <!-- directive: x-dummy_text —> <!-- directive: x-dummy:text —> <!-- directive: x-dummyText -->

29

呼び出しパターン

結果・・・

:はダメでした

04 Restrict: M

Page 30: ng-mtg#6 AngularJS ディレクティブ・パターン

AttributeとElementの解釈は同じ(camelCaseダメ)

ClassとCommentの解釈は同じ(:ダメ)

30

呼び出しパターン

Page 31: ng-mtg#6 AngularJS ディレクティブ・パターン

31

呼び出しパターン

ディレクティブ名の使い分け

わかりやすい記法 → dummy-text,dummy_text

HTMLに準拠 → data-dummy-text

XMLに準拠 → dummy:text

XHTMLに準拠 → x-dummy-text

Page 32: ng-mtg#6 AngularJS ディレクティブ・パターン

32

ちなみに・・・

呼び出しパターン

Page 33: ng-mtg#6 AngularJS ディレクティブ・パターン

28%

2%

70%

33

04 Restrict: M

01 Restrict: A02 Restrict: C

03 Restrict: E

過去の案件で実際に呼び出された形式の割合

呼び出しパターン

1個もなかった

Page 34: ng-mtg#6 AngularJS ディレクティブ・パターン

100%

34

dummy-text

過去の案件で実際に呼び出された名称形式の割合

呼び出しパターン

これしかなかった

Page 35: ng-mtg#6 AngularJS ディレクティブ・パターン

ディレクティブ名はキャメルケースだけど呼び出しをキャメルにすると 呼び出せないことがある

restrict: mはあまり使われていない。ドキュメントでもあまり触れられていない

35

呼び出しパターンを調べてみて得たこと

呼び出しは-(ハイフン)つなぎが無難

実装パターン

Page 36: ng-mtg#6 AngularJS ディレクティブ・パターン

36

実装パターン

Page 37: ng-mtg#6 AngularJS ディレクティブ・パターン

37

01

実装パターン

テンプレートパターン

02 共通パーツパターン

04 jQueryプラグインパターン

03 イベントフックパターン

Page 38: ng-mtg#6 AngularJS ディレクティブ・パターン

38

01 テンプレートパターン

実装パターン

- Template Pattern -

Page 39: ng-mtg#6 AngularJS ディレクティブ・パターン

39

共通のテンプレートを反映させるためのディレクティブ。 ng-includeと同様だが、名称が明確になりマークアップがわかりやすくなる。

実装パターン

01 テンプレートパターン - Template Pattern -

Page 40: ng-mtg#6 AngularJS ディレクティブ・パターン

<sidebar></sidebar>

40

実例

実装パターン 01 テンプレートパターン

Page 41: ng-mtg#6 AngularJS ディレクティブ・パターン

<sidebar></sidebar>

41

実例

実装パターン 01 テンプレートパターン

アクセスしたページによって activeになる要素を変えたい

今このページを表示している

Page 42: ng-mtg#6 AngularJS ディレクティブ・パターン

<sidebar></sidebar>

42

実例

angular.module('directives').directive('sidebar',function($location) { return { restrict: 'E', replace: true, templateUrl: 'views/sidebar.html' }; });

directives/sidebar.js

実装パターン 01 テンプレートパターン

外部にあるHTMLを呼び出し

タグをテンプレートで置換

Elementとして使う

Page 43: ng-mtg#6 AngularJS ディレクティブ・パターン

43

controllers/RootCtrl.js

angular.module('controllers').controller('RootCtrl', function ($scope,$location,$rootScope) { $rootScope.$on('$locationChangeSuccess', function() { $scope.current = $location.path(); }); });

<sidebar></sidebar>実例

実装パターン 01 テンプレートパターン

locationが変更されたら currentの値を現在のパスを入れる

Page 44: ng-mtg#6 AngularJS ディレクティブ・パターン

44

templates/sidebar.html

<nav> <ul class="nav nav-pills nav-stacked"> <li ng-class="{active:current==='/'}"><a href="#/">TOP</a></li> <li ng-class="{active:current==='/restrict/a'}"><a href=“#/menu/a">MENU A</a></li> <li ng-class="{active:current==='/restrict/c'}"><a href=“#/menu/b">MENU B</a></li> </ul> </nav>

<sidebar></sidebar>実例

実装パターン 01 テンプレートパターン

currentの値が一致していたら activeクラスをつける

Page 45: ng-mtg#6 AngularJS ディレクティブ・パターン

45

<sidebar></sidebar> <div ng-include=“‘templates/sidebar.html’”></div>

<sidebar></sidebar>実例

実装パターン 01 テンプレートパターン

動作は同じですが、内容が隠蔽されてシンプルに

Page 46: ng-mtg#6 AngularJS ディレクティブ・パターン

46

02 共通パーツパターン

実装パターン

- Common Parts Pattern -

Page 47: ng-mtg#6 AngularJS ディレクティブ・パターン

47

共通の動作や処理をもつパーツのディレクティブ。 ボタンやインプットフォームなど繰り返し使われる要素に有効。

実装パターン

02 共通パーツパターン - Common Parts Pattern -

Page 48: ng-mtg#6 AngularJS ディレクティブ・パターン

48

<copyright></copyright>実例

実装パターン 01 テンプレートパターン

Page 49: ng-mtg#6 AngularJS ディレクティブ・パターン

49

<copyright></copyright>実例

実装パターン 01 テンプレートパターン

Copyright © 2014 frontainer.com All Rights Reserved.

毎年更新してくれと言われる

記述の仕方忘れがち

Page 50: ng-mtg#6 AngularJS ディレクティブ・パターン

50

directives/copyright.js

<copyright></copyright>実例

angular.module('directives').directive('copyright',function() { return { restrict: 'E', replace: true, scope: { name: '@' }, template: ‘<div>Copyright &copy; {{year}} {{name}} All Rights Reserved.</div>', link: function($scope) { $scope.year = new Date().getFullYear(); } }; });

実装パターン 01 テンプレートパターン

name属性の値をscopeに入れる

現在の年をscope.yearに入れる

yearとnameをバインド

@

=

&

文字列として取得親scopeとバインディング関数として取得

Page 51: ng-mtg#6 AngularJS ディレクティブ・パターン

51

<copyright></copyright>実例

<copyright name="frontainer.com"></copyright>

<div name="frontainer.com">Copyright © 2014 frontainer.com All Rights Reserved.</div>

実装パターン 01 テンプレートパターン

こうなる

これでだいぶ使い回すことができるようになった

Page 52: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

52

実例

実装パターン 02 共通パーツパターン

Page 53: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

53

実例

実装パターン 02 共通パーツパターン

セレクトボックスまでいかない 簡易的な選択をさせたい

選択したデータがモデルに格納されるように

Page 54: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

54

実例

<div class="list-group"> <a class="list-group-item" ng-repeat="human in data" ng-click="select(human)" ng-class="{active:ngModel.id === human.id}”> {{human.name}} </a> </div>

templates/select-list.html

実装パターン 02 共通パーツパターン

クリックしたらselect関数実行

モデルのIDと自身のIDが一致したら activeクラスをつける

controllerであらかじめ作っておいた 配列の数だけ繰り返す

Page 55: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

55

実例

angular.module('directives').directive('selectList',function() { return { restrict: 'EA', replace: true, scope: { data: '=', ngModel: '=' }, templateUrl: 'js/directives/pattern/03.html', controller: function($scope) { $scope.select = function(val) { $scope.ngModel = val; } } }; });

directives/select-list.js

実装パターン 02 共通パーツパターン

dataとng-model属性に指定した値を 自身のscopeとバインドさせる

要素が選択されたときに 選択した値をモデルに格納する

Page 56: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

56

実例

angular.module('controllers').controller('RootCtrl', function ($scope) { $scope.data = [{ id: 0, name: 'Ichiro', },{ id: 1, name: 'Jiro' },{ id: 2, name: 'Hanako' } ]; });

controllers/RootCtrl.js

実装パターン 02 共通パーツパターン

選択肢を配列であらかじめ作っておく

Page 57: ng-mtg#6 AngularJS ディレクティブ・パターン

<select-list></select-list>

57

実例

実装パターン 02 共通パーツパターン

$scope.select = function(val) { $scope.ngModel = val; }

ng-click=“select(human)”

<select-list ng-model="selectedModel" data=“data"></select-list>

ng-model=“selectModel”と$scope.ngModelはバインディングしているので…

{{selectModel}}に選択したデータが入ってる

Page 58: ng-mtg#6 AngularJS ディレクティブ・パターン

angular.module('controllers').controller('RootCtrl', function ($scope) { $scope.data = [{ id: 0, name: 'Ichiro' } ]; });

<select-list></select-list>

58

実例

実装パターン 02 共通パーツパターン

配列の中身を変えればいろんな選択肢ができる

見た目はCSSでカスタマイズできる

Page 59: ng-mtg#6 AngularJS ディレクティブ・パターン

59

03 イベントフックパターン

実装パターン

- Event Hook Pattern -

Page 60: ng-mtg#6 AngularJS ディレクティブ・パターン

60

一定のイベントをフックしてDOMを操作したり ファイルをアップロードしたりするディレクティブ

実装パターン

03 イベントフックパターン - Event Hook Pattern -

Page 61: ng-mtg#6 AngularJS ディレクティブ・パターン

<textarea shift-submit></textarea>

61

実例

実装パターン 03 イベントフックパターン

Page 62: ng-mtg#6 AngularJS ディレクティブ・パターン

<textarea shift-submit></textarea>

62

実例

実装パターン

Shiftキーを押しながらEnterで送信したい

もちろん送信ボタンでも送信できる

03 イベントフックパターン

Page 63: ng-mtg#6 AngularJS ディレクティブ・パターン

<form id=“message-form” ng-submit=“send();”> <textarea shift-submit=“message-form”></textarea> <p><input type=“submit” class=“btn btn-primary”></p> </form>

<textarea shift-submit></textarea>

63

実例

実装パターン

SubmitしたいformタグのID

Submitされたときの処理

03 イベントフックパターン

Page 64: ng-mtg#6 AngularJS ディレクティブ・パターン

64

実例

angular.module(“directives").directive("shiftSubmit", function() { return { restrict: ‘AC', scope: { shiftSubmit: ‘@’ }, link : function($scope, $element){ function keydownHandler(e) { var $form = angular.element('#' + $scope.shiftSubmit); if (e.shiftKey && e.keyCode === 13) { e.preventDefault(); $form.triggerHandler('submit'); } } $element.on("keydown", keydownHandler); $scope.$on('$destroy', function() { $element.off("keydown", keydownHandler); });

directives/ShiftSubmit.js

実装パターン

<textarea shift-submit></textarea>

要素にkeydownイベントをつける

shiftSubmit属性の値をもとに form要素を取得

ShiftキーとEnterキーが押されてたら form要素をsubmit

03 イベントフックパターン

Page 65: ng-mtg#6 AngularJS ディレクティブ・パターン

65

実例

angular.module('controllers').controller('PatternCtrl', function ($scope) { $scope.messages = []; $scope.inputMessage = ‘'; $scope.send = function() { var message = $scope.inputMessage; if (!message) return; $scope.messages.unshift({ date: new Date(), message: message }); $scope.inputMessage = ''; }; });

controllers/PatternCtrl.js

実装パターン

<textarea shift-submit></textarea>

inputMessageモデルから入力された メッセージを取得

03 イベントフックパターン

Page 66: ng-mtg#6 AngularJS ディレクティブ・パターン

66

実装パターン

04 jQueryプラグインパターン - jQuery Plugin Pattern -

Page 67: ng-mtg#6 AngularJS ディレクティブ・パターン

67

AngularJSでjQueryプラグインを使いたいときのディレクティブ 参照が残らないように注意が必要なのと、プラグインでリークしないかどうかの注意も必要

実装パターン

04 jQueryプラグインパターン - jQuery Plugin Pattern -

Page 68: ng-mtg#6 AngularJS ディレクティブ・パターン

<div tooltip=“ツールチップ表示”></div>

68

実例

実装パターン 04 jQueryプラグインパターン

Page 69: ng-mtg#6 AngularJS ディレクティブ・パターン

<div tooltip=“ツールチップ表示”></div>

69

実例

実装パターン

マウスオーバーでツールチップを表示

jquery.powertip.jsを他ページで使っていたので それに合わせる必要があった

04 jQueryプラグインパターン

Page 70: ng-mtg#6 AngularJS ディレクティブ・パターン

70

実例

angular.module('directives').directive('tooltip',function() { return { restrict: 'AC', replace: true, scope: { tooltip: ‘@’ }, link: function($scope,$element) { $element.data('powertip',$scope.tooltip).powerTip(); $scope.$on('$destroy', function() { $element.powerTip('destroy'); }); } }; });

directives/tooltip.js

実装パターン

<div tooltip=“ツールチップ表示”></div>

powertipの使い方に合わせて 要素にツールチップの文言を設定

scopeが破棄されたときには powertipも合わせて破棄

04 jQueryプラグインパターン

Page 71: ng-mtg#6 AngularJS ディレクティブ・パターン

71

実例

実装パターン

<div tooltip=“ツールチップ表示”></div>

ng-repeatで回しても、Ajax等で追加されても ツールチップがちゃんと出る

<div><a tooltip="jquery.powertip.jsを使ってます">ツールチップを表示</a></div> <div><a tooltip="jquery.powertip.jsを使ってます2">ツールチップを表示</a></div> !<div ng-repeat="human in data"> <a tooltip="jquery.powertip.jsを使ってます{{$index}}">ツールチップを表示</a> </div>

04 jQueryプラグインパターン

Page 72: ng-mtg#6 AngularJS ディレクティブ・パターン

意外とパターンは少ない 活用しきれていない or モジュールが充実しているので自前実装が不要

一番多かったのは共通パーツパターン 次いでイベントフックパターン

72

パターン分けしてみてわかったこと

複雑な処理がディレクティブ化されているのを見ると嬉しくなる

実装パターン

Page 73: ng-mtg#6 AngularJS ディレクティブ・パターン

ng-grid

73

複雑な処理のディレクティブ例

実装パターン

Page 74: ng-mtg#6 AngularJS ディレクティブ・パターン

74

/*********************************************** * ng-grid JavaScript Library * Authors: https://github.com/angular-ui/ng-grid/blob/master/README.md * License: MIT (http://www.opensource.org/licenses/mit-license.php) * Compiled At: 04/29/2014 10:21 ***********************************************/ (function(window, $) { 'use strict'; // the # of rows we want to add to the top and bottom of the rendered grid rows var EXCESS_ROWS = 6; var SCROLL_THRESHOLD = 4; var ASC = "asc"; // constant for sorting direction var DESC = "desc"; // constant for sorting direction var NG_FIELD = '_ng_field_'; var NG_DEPTH = '_ng_depth_'; var NG_HIDDEN = '_ng_hidden_'; var NG_COLUMN = '_ng_column_'; var CUSTOM_FILTERS = /CUSTOM_FILTERS/g; var COL_FIELD = /COL_FIELD/g; var DISPLAY_CELL_TEMPLATE = /DISPLAY_CELL_TEMPLATE/g; var EDITABLE_CELL_TEMPLATE = /EDITABLE_CELL_TEMPLATE/g; var CELL_EDITABLE_CONDITION = /CELL_EDITABLE_CONDITION/g; var TEMPLATE_REGEXP = /<.+>/; window.ngGrid = {}; window.ngGrid.i18n = {}; !

【引用】https://github.com/angular-ui/ng-grid

Page 75: ng-mtg#6 AngularJS ディレクティブ・パターン

75

<div class="gridStyle" ng-grid="gridOptions"></div>

実装パターン

var app = angular.module('myApp', ['ngGrid']); app.controller('MyCtrl', function($scope) { $scope.myData = [{name: "Moroni", age: 50}, {name: "Tiancum", age: 43}, {name: "Jacob", age: 27}, {name: "Nephi", age: 29}, {name: "Enos", age: 34}]; $scope.gridOptions = { data: 'myData' }; });

【引用】https://github.com/angular-ui/ng-grid

view

controller

並べ替えもできる

Page 76: ng-mtg#6 AngularJS ディレクティブ・パターン

76

より良いパフォーマンスのために

Page 77: ng-mtg#6 AngularJS ディレクティブ・パターン

$templateCacheを活用しよう

gulp-angular-templatecache

$templateCache.put('hello.html', ‘<p>Hello World!!</p>’);

77

HTTPリクエストが増えすぎたときは

シンタックスハイライトが効かなかったりして読みにくいので、 GruntやGulpを使って自動的にテンプレートキャッシュを作る

grunt-angular-templates

https://docs.angularjs.org/api/ng/service/$templateCache

https://www.npmjs.org/package/grunt-angular-templates

https://www.npmjs.org/package/gulp-angular-templatecache

より良いパフォーマンスのために

Page 78: ng-mtg#6 AngularJS ディレクティブ・パターン

78

HTTPリクエストが増えすぎたときは

より良いパフォーマンスのために

こんな感じでまとめてくれる

Page 79: ng-mtg#6 AngularJS ディレクティブ・パターン

79

まとめ

最後駆け足になりましたが、まとめ

Page 80: ng-mtg#6 AngularJS ディレクティブ・パターン

ディレクティブを使うことでビューがコンパクトでわかりやすくなる

HTTPリクエストの数が増えたら$templateCacheを使ってテンプレートをひとまとめに

コントローラの負担を減らすために、DOM操作系は極力ディレクティブにしよう

80

まとめ

まとめ

共通パーツを使い回して効率UP

ディレクティブは再利用しやすいので作れば作るほど財産に

Page 81: ng-mtg#6 AngularJS ディレクティブ・パターン

81

まとめ

AngularJSの開発者が設計から実装、テスト、TIPSまでを紹介

AngularJSアプリケーション開発ガイド

http://www.oreilly.co.jp/books/9784873116679/

Web開発者にいま最も支持されているJavaScript MVCフレームワーク「AngularJS」の解説書。定型的な単純作業が繰り返されがちなWeb開発をよりシンプルで楽しいものにしようというのがAngularJSの試みです。本書ではまずAngularJSアプリケーションの構成要素を押さえた上で…

Page 82: ng-mtg#6 AngularJS ディレクティブ・パターン

82

CM

82

LIGでは、一緒にAngularJSをやっていける

フロントエンドエンジニアを募集しています。

LIG

Page 83: ng-mtg#6 AngularJS ディレクティブ・パターン

83

https://github.com/frontainer/angular-sample2

今回使用したサンプルはGithubにて公開しています

Page 84: ng-mtg#6 AngularJS ディレクティブ・パターン

84

ご清聴ありがとうございました

今回使用したサンプルはGithubにて公開しています

https://github.com/frontainer/angular-sample2