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