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

帰ってきたHolyGrailとHoryGrailの区別がつかない日記

はてなブログに帰って来ました

本気でやるならonclick属性は避けてライブラリを活用すべき

javascript

第1回 そろそろ本気で学びませんか? | Think IT

これ、今この記事書いてる時点で650以上ものブクマがされているんだけれども、あまり内容がよろしくない。
というのも、解説はとても丁寧ですごくよい内容なのだけど、サンプルコードの書き方がどうも古くさい。
onclick属性とか、今時のフロントエンドエンジニアはそんな書き方はしない(と思う)。

なぜonclickをあまり推奨しないのか

やっぱり、エンジニアとデザイナーorマークアッパーとの分業の点でHTMLの属性にスクリプトを書いちゃうのはあんまりよろしくない。
たとえばの話だけど関数の名前を変えたかったり、だとか、HTMLを変更したり、っていうときにミスが起こりやすくなってしまう。
これは分業していなくてもどちらにしろ発生してしまうことだと思う。
他にも前に書いたのだけど、aタグとかでonclickしちゃうとhrefにreturn falseとかjavascript:void(0)とか書かないといけなくなってしまう。
これは、数は少ないとはいえJavaScriptをオフにしているユーザにとってはすごくユーザビリティが悪い作りになってしまうのでできるだけ避けたいところ。

じゃあどうしたらいいの?

ってのは簡単な話で、HTMLとCSSが分けられるようにHTMLとスクリプトも分離してしまえばいいだけの話。

というわけで

ここではonclickというようにHTMLにイベントハンドラを書かなくてもこうすればいいよ、というお話をしたいと思います。

ライブラリは使おう!

さて、本気で始めるならブラウザ間の動作も完璧に理解しなくてはいけない。
が、もちろんそれはとても敷居が高いことだし、今はそのクロスブラウザにおける動作はさまざまなライブラリが吸収してくれている。
せっかくある資源を活用しないのはもったいないので、まずはライブラリを使用した実装を実践したあとに、興味のある人は中身を見ればいいと思う。
クロスブラウザの挙動を押さえるのはライブラリで実装を実践したあとでも決して遅くないよ!

サンプル

id="clickevent"という要素がクリックされたときに関数を実行するようなスクリプトを書いてみよう!

YAHOO UI Libraryの場合

ここからスクリプトをダウンロードしてもいいし、よく使われるyahoo-dom-eventというスクリプトをYahoo IncのAPIサーバからロードしてもOK。

<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> 

YAHOO.util.Event.onという関数を使ってイベントハンドラを定義してみる。

YAHOO.util.Event.on("clickevent", "click", function(){ alert('clicked!') });

この関数は第1引数に

  • id
  • HTML
  • それらの配列
  • ノードリスト

を渡して、その渡された要素に対して第2引数のイベントが発生したときに第3引数のコールバック関数を実行するための関数。
上のスクリプトを一つの文章にすると
id="clickevent"の要素がclickされたときにcallback関数(clicked!とアラート表示)を実行する
もちろん、次のようにあらかじめコールバック関数を定義しておいてもOK

var Func = function(){
  alert('clicked!');
}
YAHOO.util.Event.on("clickevent", "click", Func);

さて、実は上のスクリプト、何も気にせずに書いていると実は動かない。
おそらく、普通JavaScriptを書くとき、何も気にせずに囲まれた部分に書いてしまいませんか?
JavaScriptというのはその行が読み込まれた時点で実行をするために、もし部分に単純に上のスクリプトを書いているとDOMツリーの構築が完了していないため、id="clickevent"という要素が見つかりませんよ、というエラーが返ってくると思います。
そこで、次のようなコードに修正して、DOMツリーが構築された時点でイベントハンドラを設定するようにしてやりましょう。

function Func(){
  alert('clicked');
};
YAHOO.util.Event.onDOMReady(function() {
  YAHOO.util.Event.on("clickevent", "click", Func);
});

YAHOO.util.Event.onDOMReadyというのは、その名前の通り、DOMツリーが構築完了した時点で、渡された関数を実行するための関数です。
この中にYAHOO.util.Event.onを書いてやることで、正常にイベントハンドラが設定されることになります。

一番最初にあげた記事のサンプルには「onload」イベントハンドラでinit関数を実行していますが、これもあまりおすすめしません。
というのも、onloadイベントハンドラはブラウザによって「DOMツリー構築完了」の場合もあれば「画像も含めてHTMLの読み込みがすべて完了後」の場合もあるからです。
現時点では後者の実装の方が多いために、大きい画像が用意されているページでは、画像が読み込み終わるまでに初期化関数が実行されなくなってしまいます。
そのため、上のようにライブラリを利用し、DOMツリーが構築された段階でイベントハンドラを設定してやるようにしましょう。

cf. YUI Library Examples: Event Utility: Using onAvailable, onContentReady, and onDOMReady

APIドキュメント

ここを参考にいろいろやってみよう!
http://developer.yahoo.com/yui/docs/

jQueryの場合

jQueryは今もっとも熱いライブラリ!
今使うならこれをオススメする。
さて、上と同じことをjQueryでやってみましょう。

$('#clickevent').click(function(){
  alert('clicked');
});

jQueryの特徴はチェーンメソッドといって、$()関数で要素を決定したあとに、ひたすら「.(ドット)」でメソッドをつなげていくこと。
$()関数に続いて「.(ドット)」でつながれた関数が$()関数で指定された要素に適用されていく。
つまり、上の場合は#clickeventというCSSセレクタで指定された要素に対して「click」というメソッドがつながれているので、#clickeventがクリックされたときに、関数が実行される、という形になる。

さて、これも上と同じようにこのまま書いてしまっても動かない。
jQueryの場合は次のように書いてあげよう。

$(document).ready(function(){
  $('#clickevent').click(function(){
    alert('clicked');
  });
})

また、上のような書き方は次のように省略して書くこともできます。

$(function(){
  $('#clickevent').click(function(){
    alert('clicked');
  });
});

YAHOO UI Libraryに比べてかなりスマートに書けましたね。

cf. .ready() – jQuery API

APIドキュメント

ここを参考にいろいろやってみよう!
http://docs.jquery.com/Main_Page

まとめ

  • onclick属性は使うと後々で面倒!
    • 運用負荷はやっぱり下げたいよね!
  • ライブラリを恐れるな!
    • ライブラリを一度使っちゃうと依存しちゃうかも、でもやっぱりまず動くものを作ることが重要だよね!

といった感じでしょうか。

他にもいろいろと説明したいことはあるのですが*1思ったよりも長くなってしまったので今日はこの辺でおしまいです。

今回の内容に興味を持った人は是非

  • addEventListener
  • attachEvent

について調べてみてください!

追記
これよりも本当に前の段階でJavaScriptを本気で勉強したいのであれば

のような内容が適切だと考えています。

JavaScript 第5版

JavaScript 第5版

まるごとJavaScript & Ajax ! Vol.1

まるごとJavaScript & Ajax ! Vol.1

*1:キャメルケースの話とか、YUIの時はaタグのclickにイベントハンドラやるときはYAHOO.util.Event.stopEvent(e)とかで遷移を制限しないといけない、とか