#はじめに
「文書構造はHTMLに、処理はJavaScriptにしっかり分離しましょう。 HTMLにonclickとか書くのはダメ」と覚えてから、これまで当たり前のようにそういう考え方でやってきましたが、AngularJSを触りだした頃から、その感覚に変化を感じてます。
AngularJSを見ていると、例えばngClickなどはHTMLに呼び出す関数を書くスタイル(宣言的なイベントハンドラ)がデフォルトで、HTMLから分離していません。
<button ng-click="test()">click</button>
$scope.test = function() {
alert("hello");
};
けれども、この手法に従うなら、test()という関数がコントローラに登録されていて、DOMセレクタのことをいちいち考える必要はありませんし、挙動(振る舞い)を直接HTMLのノードに適用するだけなので、実装もメンテナンスも楽に感じます。
DOMとの面倒なやり取りも省略できますし、とにかく分かりやすい。
#一般的な概念では分離するのが基本
「文書構造はHTMLに、処理はJavaScriptにしっかり分離する」という概念に基づけば、
このような形が一般的でしょう
<button id="test">click</button>
document.getElementById("test").onclick = function (){
alert("hello");
}
jQueyだとこんな感じかな
$("#test").on("click",function(){
alert("hello");
});
しかし、何故こういうコードを追い求めるのか?
おそらく以下のように思っている方が多いのでは無いかと
- javascriptをオフにしている人がいる
- イベント処理の呼び出し方法がブラウザごとに異なる
- 文書構造と挙動(振る舞い)をミックスさせると、難読で保守しづらいコードができあがる
ですが、今時javascriptをオフにしている人なんて殆どいませんし、イベント処理の呼び出し方法も知識さえ身につけておけば、ブラウザごとの解釈の差は回避できますし、読みづらくなる・スパゲティ化するというならば、jQueryのセレクタのような、DOMのノードツリーに依存するコードの方が、読みづらくなる・スパゲティ化の原因になることが多いように感じます。
例えば
$("li.katsuo").parent("#isono").next("#isasaka")
#####"カツオが暮らす磯野家の隣家の伊佐坂家" みたいな
#プログラムの原点に立ち戻って
書くなら、このような形でしょう。
<button onclick="test()">click</button>
function test(){
alert("hello");
}
でも、何か違う。タグ内にスクリプトを書くのは気持ち悪い。
ではどうするか?
次のような要素の挙動を制御する記述的属性を適用するのが理想だと思います。
<button data-alert="hello">click</button>
<button data-alert="world">click</button>
・・・・
・・・・
var alertObj = document.querySelectorAll('[data-alert]');
for(var i in alertObj) {
alertObj[i].onclick = function (){
alert(this.dataset.alert);
}
};
これなら要素が変動しても、data属性を付与さえすれば済みますし、属性の値と処理をバインディングできるので、シンプルで保守的です。
前述したように最近はHTML内部のこのようなロジックが好きです。
これまで長い間、コンテンツ(HTML)と挙動・振る舞い(JavaScript)を分離し、(CSSもそうですが)インラインのスクリプティングを避け、とにかく「外部ファイル化!外部ファイル化!」声高らかに叫んできましたが、実際に考えをちょっと変えてやってみると大幅に時間を節約でき、尚かつコンポーネント自体も柔軟になることが分かりました。
#まとめ
jsのロジックをHTMLに埋め込んでもいいんじゃないか。
ただ、HTMLに埋め込むだけではなく、設定を付与する形で。