脱jQueryに向けた第一歩
UI開発者 笹この記事はミツエーリンクスアドベントカレンダー2019の2日目の記事です。
脱jQueryするべきなのか
jQueryは、JavaScriptをより簡易的に記述することができ、各ブラウザへの互換性を持つため非常に便利なライブラリです。しかし、リソース読み込みによるパフォーマンスの低下も懸念されています。
表示パフォーマンスに目が向けられている昨今、jQueryを利用しないことも1つの選択肢になるのではないでしょうか。
また、ブラウザも進化しておりブラウザごとにJavaScriptの動作が変わることもほとんどなくなりました。
もしかしたら、もともとクロスブラウザ対応として生まれた側面が強いjQueryを利用しないタイミングが来ているのかもしれません。
jQueryを無理にやめようとしない
とは言え、いままでjQueryを使って書いてきたコードをすべてネイティブに書き換えるには、覚えること・考えることが多く時間がかかって大変です。
まずはいつも書いているjQueryのコードを少しだけネイティブに置き換えていくところから始めでみるのはいかがでしょうか。
jQueryを利用して開発を進めていたとしても、ネイティブのJavaScriptは利用できますので、上手に併用することで「脱jQuery」を目指してみましょう。
本記事では主要ともいえる、DOM取得、クラスの操作、属性取得・設定、イベントの設定・削除の置き換え例を紹介します。
DOM取得
jQueryでは$('セレクター');
と記述していました。
ネイティブのJavaScriptにも同様のCSSセレクターで取得する機能がありますが、より高速にDOMを取得する方法も存在します。
CSSセレクターで取得
ページ内に1つまたは初めの1つ目を取得
// jQuery
const $hoge = $('div[data-hoge]').eq(0);
// Native
const hoge = document.querySelector('div[data-hoge]');
querySelector
ではHTMLElement
という1つのHTML要素としてDOMが取得されます。
複数存在するものをすべて取得
// jQuery
const $listItem = $('.list li');
// Native
const listItem = document.querySelectorAll('.list li');
querySelectorAll
ではNodeList
というHTML要素の集まりとしてDOMが取得されます。
※NodeList
は配列と似ているオブジェクトです。NodeList ≠ 配列なので注意してください。
CSSセレクターでの要素取得はjQueryでの要素取得とも似ている部分があり、便利なように感じますが、スピード面では劣ります。
なぜなら、querySelector
、querySelectorAll
では取得するDOMのコピーを作成して保持します。
一方、以下で紹介するgetElementById
などはコピーを作成せず取得するDOMにリンクしている状態になります。
querySelector
、querySelectorAll
はコピーを作成する分、処理にコストがかかるためgetElementById
などと比べると遅いのです。
パフォーマンスを求めるのであれば次に紹介する getElementById
や getElementsByClassName
を利用することを検討してみてください!
要素名で取得
// jQuery
const $div = $('div');
// Native
const div = document.getElementsByTagName('div');
getElementsByTagName
ではHTML Collection
というHTML要素の集まりとしてDOMが取得されます。
※HTML Collection
もNodeList
と同様に配列と似ているオブジェクトです。HTML Collection ≠ 配列なので注意してください。
class名で取得
// jQuery
const $fuga = $('.fuga');
// Native
const fuga = document.getElementsByClassName('fuga');
getElementsByClassName
もgetElementsByTagName
と同様にHTML Collection
というHTML要素の集まりとしてDOMが取得されます。
id名で取得
// jQuery
const $hoge = $('#hoge');
// Native
const hoge = document.getElementById('hoge');
idは1つのページ(document)内に1つというルールのため、getElements
(複数形)ではなくgetElement
(単数形)であることに注意してください。
また、取得できるDOMはNodeList
やHTML Collection
ではなくHTMLElement
として取得されます。
jQueryとあわせて利用する
以下のように、DOMの取得のみネイティブのJavaScriptで実行するだけでも、わずかですがパフォーマンスの改善につながります。
また、ネイティブのJavaScriptで取得したDOMも$()
を利用してjQuery Objectに変換することでjQueryメソッドを利用することが可能です!
// jQuery
const $root = $('#root');
const $link = $root.find('a');
$link.addClass('hoge');
// Mix
const root = document.getElementById('root');
const link = root.querySelectorAll('a');
$(link).addClass('hoge');
DOMをまとめて操作する
jQueryでは取得した複数のDOMに対しても.addClass()
を使えばまとめてクラスを付与することが可能でしたが、ネイティブのJavaScriptではそれができません。
そのため、複数のDOMに対してまとめて何かしらの処理を行う場合はfor文を利用します。
const link = document.querySelectorAll('a');
for (let i = 0, length = link.length; i < length; i++) {
// ここに処理
}
クラスの操作
jQueryでは.addClass()
でクラスの追加、.removeClass()
でクラスの削除、.toggleClass()
でクラスの付け外しができます。
さらには、.hasClass()
で特定のクラスを持っているかの判別が可能です。
安心してください。ネイティブのJavaScriptも同様にクラスを操作することが可能です!
クラスの追加
// jQuery
$('#hoge').addClass('huga');
// Native
document.getElementById('hoge').classList.add('huga');
クラスの削除
// jQuery
$('#hoge').removeClass('huga');
// Native
document.getElementById('hoge').classList.remove('huga');
クラスの付け外し
// jQuery
$('#hoge').toggleClass('huga');
// Native
document.getElementById('hoge').classList.toggle('huga');
クラスを持っているか
// jQuery
$('#hoge').hasClass('huga');
// Native
document.getElementById('hoge').classList.contains('huga');
jQueryとあわせて利用する
DOM取得をjQueryで行った場合でも、for文を利用してそれぞれの要素に対してネイティブのJavaScriptを利用することが可能です。
// jQuery
const $root = $('#root');
const $link = $root.find('a');
$link.addClass('hoge');
// Mix
const $root = $('#root');
const $link = $root.find('a');
for (let i = 0, length = $link.length; i < length; i++) {
$link[i].classList.add('hoge');
}
属性取得・設定・削除
jQueryでは取得と設定はどちらも.attr()
を利用しますが、ネイティブでは取得にgetAttribute
、設定にsetAttribute
を利用します。
削除の際は同様にremoveAttribute
を利用します。
属性を取得
// jQuery
$('img#hoge').attr('src');
// Native
document.getElementById('hoge').getAttribute('src');
属性を設定
// jQuery
$('img#hoge').attr('src', './image/img-01.jpg');
// Native
document.getElementById('hoge').setAttribute('src', './image/img-01.jpg');
属性を削除
// jQuery
$('img#hoge').attr('src');
// Native
document.getElementById('hoge').removeAttribute('src');
jQueryとあわせて利用する
クラスの操作同様、jQueryで行った場合でも、for文を利用してそれぞれの要素に対してネイティブのJavaScriptを利用することが可能です。
属性を付与しているのか、取得しているのか、削除しているのかは、ネイティブのJavaScriptの方がgetAttribute
、setAttribute
、removeAttribute
と明示されてるためわかりやすいように見えます。
// jQuery
const $root = $('#root');
const $link = $root.find('a');
$link.each(function () {
$(this).attr('data-href', $(this).attr('href'));
});
$link.removeAttr('href');
// Mix
const $root = $('#root');
const $link = $root.find('a');
for (let i = 0, length = $link.length; i < length; i++) {
const target = $link[i];
target.setAttribute('data-href', target.getAttribute('href'));
target.removeAttribute('href');
}
イベントの登録・削除
イベントの設定にはメソッド名が異なるのみで大きな違いはありません。
しかし、削除の際はひと手間必要なので注意しましょう。
イベントの登録
// jQuery
$('a#hoge').on('click', function () {
// クリック時に行う処理
});
// Native
const handler = function () {
// クリック時に行う処理
};
document.getElementById('hoge').addEventListener('click', handler, false);
イベントの削除
// jQuery
$('button#hoge').off('click');
// Native
const handler = function () {
// クリック時に行う処理
};
document.getElementById('hoge').removeEventListener('click', handler, false);
イベントの削除には上記の通り、イベントタイプ('click'
)や実行文(handler
)の引数が必要になります。
そのため、jQueryの様にイベントタイプのみでのイベントの削除はできません。
イベントを削除する際は、addEventLinstener
と同じ値をremoveEventListener
に指定することを推奨します!
これで簡単な処理なら置き換えることができます!
試しに、<div id="root">
にクラスhoge
を追加し、その中のすべてのa要素
のhref属性
をdata-href属性
に書き換え、クリック時にdata-href属性
に設定されたURLのページに遷移する処理をjQueryからネイティブのJavaScriptに書き換えてみると以下のようになります!
// jQuery
const $root = $('#root');
const $link = $root.find('a');
$root.addClass('hoge');
$link.each(function () {
$(this).attr('data-href', $(this).attr('href'));
});
$link.removeAttr('href');
$link.on('click', function (event){
event.preventDefault();
window.location.href = $(this).attr('data-href');
});
// Navive
const root = document.getElementById('root');
const link = root.querySelectorAll('a');
root.classList.add('hoge');
for (let i = 0, length = $link.length; i < length; i++) {
const target = $link[i];
target.setAttribute('data-href', target.getAttribute('href'));
target.removeAttribute('href');
target.addEventListener('click', function (event){
event.preventDefault();
window.location.href = this.getAttribute('data-href');
});
}
まとめ
単純なDOMの操作であれば少し覚えてしまえば難なく移行できる気がしませんか?
多少の不安があっても、jQueryを読み込みながら利用することもできますのでわからない部分はjQueryを使えば大丈夫です!
1からネイティブのJavaScriptの勉強するとなると、jQueryと比べ構文が大きく異なるので敷居が高いように感じてしまいますが、あらかじめjQueryを読み込んで動作するものを用意して、同じ動作をするように少しずつ書き換えていけば、「動かない!わからない!」という状況になりにくいので、チャレンジしやすくなります。
「jQueryでこう書いている部分はネイティブではどう書くんだろう?」から始めることで、脱jQueryに向けての一歩を踏み込んでみてはいかがでしょうか?
少しでもjQueryからネイティブへの移行を考えている方のお力になれれば幸いです。