Code

2015年4月19日日曜日

AngularJS Directive の使い方

 おととい別チームの Front End Dev に Directive のオーダーについて聞かれました。そのプロジェクトでは ng-model の隣に、入力値のチェックやフォーマットを全て個々の Directive で行われています。いっぱい Directive が書かれていて、コードを読むにはちょっと大変です。。。それで、問題となってたところは二つ Directive の中に、onblur を使って、入力値をチェックしたり、値を変えたりしてました。ただ、onblur のコールオーダーによりページには変な動作になりました。それで、onblur の handler の呼び順番変えられるかと聞かれました。
 少し、彼らの Directives を見てみると、あまりいいアプローチと思ってませんでした。なぜなら、priority も設定してないし、ng-model の中に formatter と parser キューがありますので、本らなら、それを使って、すぐできる機能なのに、全て onblur の中に書いてしました。
 まぁ、一番大事なのは問題を解決するので、まず、directive に priority という属性がありますので、それを使って、direcitive の link function を実行するオーダーが変更できます。具体的に言うと、AngularJS はまず一つの element に attach した全ての directive を array に入れて、そのあと、priority を使って、Sort してから、link を呼び出してます。それで、directive の onblur を呼ぶ順番は変えられます。
 まぁ、もう一つの方法は $timeout を使って、次の digest circle に実行することです。ただ、これは間違いだと思っています。$timeout はあまりにも使いすぎてる感じがあります。何か動かなかったら、すぐ $timeout を呼ぶとか。。。
 注意すべきところは $timeout では、$rootscope.apply() が呼ばれているので、全てのあたりが一回 digest されます。もし複数の $timeout が呼ばれるなら、ページはずっとリフレッシュされます。。。これは AngularJS が重いと言われた原因の一つだと思います。

 今回なら、ng-model すでに formatter と parser があるので、それを使うべきだと思います。それに、一つの機能を一つの directive に入れるのはあまり良くないです。いっぱい directive になると、さらにその中に jquery などを使って、DOM 操作すると、オーダーが難しくなります。もし、単独の directive を使うなら、カテゴリにより機能をまとめるべきです。例えば、入力値のフォーマットをチェックするなら、全てのチェックの一つの directive にまとめた方がいいです。そうすると、$validate でエラーメッセージを設定には簡単になります。表示の順番も操作しやすくなります。
 
 本来なら、Framework は裏でいっぱいやっているので、その処理を知るべきだと思います。例えば、directive の compile、link function はどのように呼ばれているかとか、angular の bootstrap はどのように実行しているかとか。それを知らないと、パフォーマンスのいいアプリは作れるには難しいです。
 
 それでは。

0 件のコメント:

コメントを投稿