読者です 読者をやめる 読者になる 読者になる

プログラマー幸福論

プログラム関係の雑記やcodicの開発日誌

jQuery Behaviors

f:id:namba0219:20130613182328j:plain

photo credit: paul bica via photopin cc

Summaryサマリ

jQuery Behaviorsは、jQuery を使った開発の1つのアプローチです。jQuery behaviorsは、jQueryを使った中規模Webアプリケーションにおいて、肥大化するjQueryコードを効率的に管理し、再利用性を高めるためのプラクティスです。

※ Behaviorの本質は、jQueryを使った開発のためのプラクティスであり、プラグインを提供することでありません。プラグインとしてダウンロードできますが、それはただの実装例ですので、あなたが自分好みにカスタマイズしてください。

Getting Started

なにはともあれ、あなたの環境で動くようになるまでを説明しておきます。

1. 構成

Github からダウンロードできます。jQuery Behaviors を動かすには、2つの設定が必要です。1つは、jQuery本体および jquery-behaviors.js をリンクさせ、必要な Behavior の定義をいくつかリンクさせます。最後に、.setupBehaviors() を呼び出せば、準備は完了です。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery-behaviors.js"></script>
<script type="text/javascript" src="js/behaviors/behavior-update.js"></script>
<script type="text/javascript" src="js/behaviors/behavior-remove.js"></script>
<script type="text/javascript">
$(function() {
    $(document).setupBehaviors();
});
</script>

2. Behaviorの割り当て

特定の要素への Behavior の割り当ては、.behavior というクラスと data- 属性を使い行います。data 属性は、data-behavior-[Behavior名] という属性名で、Behavior割り当て時のオプションをJSONで指定します。以下の例では、リンクをクリックすると下のボックスを表示する記述です。

 

<a class="behavior" data-behavior-show="{trigger:'click',target:'#box'}">SHOW</a>
<div id="box" style="display: none;">
Hidden
</a>

 

What's behavior?なんぞや

再利用性

jQueryを使った開発では、プロジェクトが中規模以上になってくると、以下のようなちょっとしたコードが大量発生します。1つ2つなら問題ありませんが... 大量に発生します。

$('#btn').click(function() {
    $('#box').show();
});

jQuery Behaviorsのプラクティスでは、.show() や .ajax() のようなjQueryのメソッドをそれぞれ Behavior(振る舞い)として再定義しコンポーネント化することで、効率よく再利用、管理できるようにします。

ID・クラスはCSSのもの

jQueryを使った開発では、イベントの割り当ての際にIDやクラス属性を利用するため、DOMとコードが密接に依存し合います。DOMをちょっと変更したら、コードも見直さなければならない。こういったことが、jQueryスパゲッティを生み出す原因にもなります。

またIDやクラスは、CSSでも利用されます。だからデザインとDOM、コードが密接に関係し合うことになります。

jQuery Behaviors は、DOMドリブンでの開発を推奨します。jQuery Behaviors では、特定のDOM要素への Behaviors の割り当ては、data 属性を使い行います。data 属性は、data-behavior-[Behavior名] という属性名で、Behavior割り当て時のオプションをJSONで指定します。以下の例では、「Show」リンクをクリックすると下のボックスが表示される例です。

<a class="behavior" data-behavior-show="{trigger:'click',target:'#box'}">SHOW</a>
<div id="box" style="display: none;">
Hidden
</a>

実際のBehaviorの定義は別にあるのですが、DOMの記述だけで何が行われているか理解できると思いませんか?これが Behaviorの目指すところなのです。従来のjQueryのコードだと「ボタン」に付けられたIDやクラス名をでコードを検索してみないとわからないでしょ?。

jQuery Behaviors の使い方

behavior の簡単な使い方を説明します。

Behavior の種類

Behaviorには、いくつかの種類があります。
  1. 基本コンポーネント - Ajax通信やDOM
    ajax, update, show, hide, remove, priodical
  2. UIコンポーネント - タブやカルーセル
    tab, dialog, dropdown
  3. jQuery Plugin のブリッジ - 他のプラグインとの連携
    litebox
  4. ファサード - コンポーネントの組み合わせ
    ajaxupdate, ajaxdialog, logindialog

Best Practicsプラクティス

DOMとコードの分離

Behaviors が指向するプラクティスの一つに、DOMとコードの分離があります。下記の例は、よくあるjQueryを使った制御の例ですが、IDやクラス属性とコードが密接に関係しています。

Behaviorsでは、すべてのイベントバインディングを .behavior というクラス属性とdata-behavior- によって己申告制で実現します。これは、DOMが「はい!私にBehaviorを割り当てて!」と言う感じです。これにより、DOMに割り当てられているBehavior(つまりイベント)が一々JSファイルを開かなくても、DOMから読み取れるというメリットがあります。

また、自己申告制にはもうひとつメリットがあります。あたりまえですが、DOM要素を削除したらBehaviorの割り当ても削除されます。あるいは、DOM要素をコピーしたら、その要素も同じ挙動するはずですね。

Behaviorsでは、DOMとBehavior がセットで管理されるため、従来の1つ1つイベントを割り当てていく方法に比べ、コードの管理が簡単なものになります。

デザイナーとプログラマーの連携

jQUery Behaviorsは、デザイナーとプラグラマーがうまく連携して作業することの手助けをしてくれます。デザイナーは、コードを書くことなく(JSONくらいは覚えてね)すべての挙動を data属性で記述するだけでいいのです。そして、足りない Behaviorやオプションがあればプログラマーに「こんなの作って!」と言えばいいのです。簡単でしょ!

<a class="behavior" data-behavior-show="{trigger:'click',target:'#box'}">SHOW</a>
<div id="box" style="display: none;">
Hidden
</a>

再利用性

jQuery Behaviorsでは、汎用化できないという理由でプラグインにするまでもないが複数の画面で利用するコードを、Behaviorとして定義することができます。

カスタマイズ

既存の behavior を少し変えたくなったら、オプションを追加します。specialFlag みたいなその場限りのオプションでも構いません。ここで重要なのは、既存でその Behaviorが割り当てられているDOMに影響を与えないようにすることであって、プラグインのように汎用性を考慮する必要はありません(それがボトムアップなのさー)

リファクタリング

大量の Behavior のコードを書いていると、オプション名や指定の仕方をリファクタリングしたい衝動に駆られます。そんな時でも Behaviorは、緩やかに改善していく方法を提供します。やり方は簡単です。

  1. Behavior AをコピーしてBehavior Bとする
  2. Behavior B をリファクタリング
  3. ちょっとずつ Behavior B に移行していく

ファサード

コンポーネントをイベントで連携させたものを予め作っておけば、DOMへの記述が少なくてすみます。また、特定のパラメータなどを Behaviorに持たせ集中管理することもできます。Behaviorを組み合わせたBehaviorをファサードと言います。以下は、ログインダイアログを表示させるファサードです(AjaxとDialogの組み合わせ)。

!function ($) {
    var LoginDialog = function(element, options) {
        var self = this;
	    self.element = element;
            self.options = $.extend({},{
        }, options);
        self._setup();
    };
    LoginDialog.prototype._setup = function() {
        var self = this;
        $(self.element).applyBehavior('ajax', {
            trigger: 'click', 
            action: '/login_dialog.html'
	    });	
	    $(self.element).applyBehavior('dialog', {
            trigger:'complete.ajax.behavior'
        });
    };
    $.registerBehavior('logindialog', LoginDialog);
}(window.jQuery);

こんな感じで1つつくっておけば、プロジェクト内のどのコードからもこんな感じでログインダイアログが表示できます。便利でしょ!

<a href="javascript:;" class="behavior" data-behavior-logindialog>ログイン</a>

ボトムアップ

TODO : 

無理しない

すべての処理をBehaviorで実装できれば、コードはシンプルでとても管理しやすいでしょう。しかし、時には表現できなものもあります。そんなときは無理する必要はありません。無理だと感じたら、その部分については、従来どおり jQueryのコードを書いてください。それがボトムアップアプローチです。

高度なテクニック

イベントチェイン

簡単なDOM操作はわかりましたが、複雑な処理はどうやればいいでしょうか。 実は、Behaviors ではイベントを使って Behaviorを連携させることで複雑な処理を実現する仕組みがあります。以下の例は、一定間隔でAjaxリクエストを投げ、特定の要素を更新するものです。periodical[!clock] -  Ajax[!complete] - Update という順にイベントが伝播していきます。

<a class="behavior" data-behavior-periodical="{interval:1000}" data-behavior-ajax="{trigger:"clock.periodical",action:'/update'}" data-behavior-update="{trigger:'complete.ajax',target:'this',type:'replace'}">[1]</a>

Ajax通信

Behaviorsでは、Ajaxのレスポンスは更新された部分的なHTMLを返す方式を推奨しています。理由は簡単で、Ajaxの結果をハンドリングする処理をコーディングしたくないからです。

<a class="behavior" data-behavior-ajax="{action:'/get'}" data-behavior-update="{trigger:"complete.ajax.behavior",target:'#contents'}">Show</a>
<div id="contents">
</div>

※ 仕組みを考えれば、JSON形式を返し、jquery-templete のようなもので整形することを Behavior 化することもできるかもしれませんが、やってみたことがないので誰か考えてみてください。

イベントの再割り当て

jQueryを使った開発では、しばしば Ajaxなどにより動的に読みまれたコンテンツのイベントの再割り当てが問題となります。jQuery Behavior では、.setupBehaviors() というメソッドでこれを解決します。これを動的に読み込んだ部分に対して使うことで、Behavior が再割り当てされます。

※ 処理軽減のために .live() 相当を使うこともできるが、自己申告制という原則に反するので、基本コンポーネントでは使いません。

<script>
$(function() {
    $('<a href="#" class="behavior" data-behavior-show>')
    .appendTo('<body>')
    .setupBehaviors();
})
</script>

 

ごめんなさい。
この記事は書きかけです。
実際の例を見たい方は、codic のソースを見てください。setup.js ってやつがBehaviorの定義です。