DOMおれおれAdvent Calendar 2015 – 23日目

jQueryをまるまる使う程じゃないけどちょっとjQuery的な機能が欲しいなという場面はときどきあるかと思うんですが、そういうときに「jQuery風の機能」を自作するための実装例を幾つか挙げてみたいと思います。
セレクターから検索して、各要素を操作
こんな風に使いたい場合。
1 2 | var $el = $( '#foo .bar [boo=123]' ); $el.css({ color: 'red' }); |
以下の二つの機能が必要です。
- セレクターから要素を取得し、確保しておく
- 確保した要素全てに対して処理をする
他にも諸々の機能が必要かと思いますが、それらの基盤となるのが本機能ですね。
セレクターから検索して要素を確保
これで配列風に扱えるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // インターフェイス。これを使う。 function $(selector) { return new MyQuery(selector); } // コンストラクター。実態。 function MyQuery(selector) { var nodes = document.querySelectorAll(selector); // 配列風に各要素を保持 for ( var i=0, l=nodes.length; i<l; i++) { this [i] = nodes[i]; } // 配列風に要素数を保持 this .length = nodes.length; } |
1 2 | var $links = $( 'a' ); console.log($links.length, $links[0]); |
といっても何も機能がないので大して嬉しくないですね。ここからです。
各要素に対して一括操作
forEach()
なものを実装します。というか配列が持つ関数をそのまま使っちゃって大丈夫です。
1 | MyQuery.prototype.forEach = Array.prototype.forEach; |
あら簡単。(IE 9+。IE 8の場合は自前で実装します。) これだけでもだいぶ使えると思います。
1 2 3 4 | var $links = $( 'a' ); $links.forEach( function (el, index) { console.log(el, index); }); |
ちなみにjQueryは forEach()
じゃなくて each()
というAPIで、コールバック関数に与えられる引数の順序が違います。けどまあいいよね。
API設計の基盤思想
jQueryは使い心地が良いのですが、以下の共通仕様が大きく貢献しているものと思います。
- メソッドチェインのため、操作後オブジェクト自身を返す
- 対象の有無による分岐を省くため、検索結果が0件の状態でも各機能でエラーにしない
というわけで、これらに気を付けながら諸々実装していきます。
イベント監視
割とよく使う気がしますので、これからいきましょう。 on()
は addEventListener()
で実装できます。
1 2 3 4 5 6 | MyQuery.prototype.on = function (type, listener) { this .forEach( function (el) { el.addEventListener(type, listener); }); return this ; }; |
簡単だ!
拡張しやすくする
jQueryのメソッドは $.fn
に登録する事で自由に追加できるようになっています。真似ておきましょう。
1 | $.fn = MyQuery.prototype; |
できたよ
全然APIないですが、基本的にはこんなもんでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // インターフェイス。これを使う。 function $(selector) { return new MyQuery(selector); } // コンストラクター。実態。 function MyQuery(selector) { var nodes = document.querySelectorAll(selector); // 配列風に各要素を保持 for ( var i=0, l=nodes.length; i<l; i++) { this [i] = nodes[i]; } // 配列風に要素数を保持 this .length = nodes.length; } $.fn = MyQuery.prototype; $.fn.forEach = Array.prototype.forEach; $.fn.on = function (type, listener) { this .forEach( function (el) { el.addEventListener(type, listener); }); return this ; }; |
30行にも満たないコードですが、これでこんな風に使えます。
1 2 3 | $( '#el' ).on( 'click' , function (event) { alert( '!' ); }); |
ちょっとサンプルコード書きたいけどjquery.jsを探してくるの面倒だなーみたいなときに便利かもしれません。良い感じに雛型が整備できるなら良いけれど。
というのライブラリーを作ってます
よければご利用ください。