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を探してくるの面倒だなーみたいなときに便利かもしれません。良い感じに雛型が整備できるなら良いけれど。
というのライブラリーを作ってます
よければご利用ください。
