Smart Communication Design Company
ホーム > ナレッジ > Blog > フロントエンドBlog > 2019年12月 > 脱jQueryに向けた第一歩

脱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での要素取得とも似ている部分があり、便利なように感じますが、スピード面では劣ります。

なぜなら、querySelectorquerySelectorAllでは取得するDOMのコピーを作成して保持します。

一方、以下で紹介するgetElementByIdなどはコピーを作成せず取得するDOMにリンクしている状態になります。

querySelectorquerySelectorAllはコピーを作成する分、処理にコストがかかるためgetElementByIdなどと比べると遅いのです。

パフォーマンスを求めるのであれば次に紹介する getElementByIdgetElementsByClassName を利用することを検討してみてください!

要素名で取得

// jQuery
const $div = $('div');

// Native
const div = document.getElementsByTagName('div');

getElementsByTagNameではHTML CollectionというHTML要素の集まりとしてDOMが取得されます。

HTML CollectionNodeListと同様に配列と似ているオブジェクトです。HTML Collection ≠ 配列なので注意してください。

class名で取得

// jQuery
const $fuga = $('.fuga');

// Native
const fuga = document.getElementsByClassName('fuga');

getElementsByClassNamegetElementsByTagNameと同様にHTML CollectionというHTML要素の集まりとしてDOMが取得されます。

id名で取得

// jQuery
const $hoge = $('#hoge');

// Native
const hoge = document.getElementById('hoge');

idは1つのページ(document)内に1つというルールのため、getElements(複数形)ではなくgetElement(単数形)であることに注意してください。

また、取得できるDOMはNodeListHTML 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の方がgetAttributesetAttributeremoveAttributeと明示されてるためわかりやすいように見えます。

// 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からネイティブへの移行を考えている方のお力になれれば幸いです。