【脱・jQuery】jQueryで書いたAjaxをJavaScriptのFetch APIで書き直してみた

はじめに

これまでJavaScriptの処理を書くときはjQueryを使っていました。昔のJavaScriptはブラウザ互換性問題などがありとてもゴタゴタしていたので、jQueryを知ってからはその便利さに頼りっきりになっていました。

しかし、最近は主要ブラウザでの互換性問題はほとんど解消され、jQueryを使うメリットが薄れてきています。むしろ、jQueryを導入する手間だったり、導入してからもバージョン管理したりとデメリットのほうが目立ってくるようになりました。

そこで、ようやく重い腰を上げて「脱・jQuery」をここに宣言し、jQuery卒業を図るべく、プレーンなJavaScriptの勉強をイチからはじめました。その第一歩として、今までjQueryで書いていたAjaxをJavaScriptのFetch APIで書き直してみました。

HTML

Laravelで作ったWebアプリなので、ところどころHTMLではない書き方をしていますが気にしないでください。

<span id="heart-{{ $post->id }}" class="heart"
      data-url="{{ route('posts.heart', ['post' => $post->id]) }}">
    <i class="far fa-heart"></i>
    <span id="count-{{ $post->id }}" class="count">
        @if ($post->heart > 0)
            {{ $post->heart }}
        @endif
    </span>
</span>

以下のようなハートをクリックするとサーバーにリクエストを送り、カウントアップしてクライアントに戻ってくるという処理です。

jQueryのAjax

リファクタリング対象であるjQueryのAjax処理は以下のようになっています。

$(function() {
    $('[id^=heart]').on('click', function() {
        $.ajaxSetup({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
        });

        $.ajax({
            type: 'POST',
            url: $(this).data('url'),
            dataType: 'json'
        }).done(function(data, textStatus, jqXHR) {
            // 成功時の処理
            $('#count-' + data.id).text(data.heart);
        }).fail(function(jqXHR, textStatus, errorThrown) {
            // 失敗時の処理
            alert(jqXHR.responseText);
        });

        return false;
    });
});

JavaScriptのFetch API

上記と同じ処理をJavaScriptのFetch APIを使って書き直したものが以下です。

window.onload = () => {
    document.querySelectorAll('[id^=heart]').forEach((heart) => {
        heart.addEventListener('click', (event) => {
            let token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
            let url = heart.getAttribute('data-url');
            fetch(url, {
                method: 'POST',
                headers: {
                    'X-CSRF-TOKEN': token,
                },
            }).then((response) => {
                if(response.ok) {
                    return response.json();
                }
                throw new Error();
                console.log(response);
            }).then((json) => {
                document.querySelector('#count-' + json.id).textContent = json.heart;
            }).catch((error) => {
                throw new Error();
                console.log(error);
            });
            event.preventDefault();
        });
    });
};

Fetch API

JavaScriptのAjaxでは長らくXMLHttpRequestが使われてきましたが、現在の主流はFetch APIとなっています。ただし、Fetch APIはIEでサポートされていないため、使う際は注意が必要です。

サーバーにリクエストを送るフェーズ、レスポンスを受け取るフェーズ、エラーをキャッチするフェーズをメソッドチェーンで繋いでいく書き方は、jQueryのAjaxととてもよく似ています。

アロー関数式

function式をより短く書けるようにしたのがアロー関数式です。引数が1つの場合は()の省略ができます。

Document.querySelector()Document.querySelectorAll()

DOM要素を取得するにはDocument.getElementById()などが使われていましたが、CSSセレクタと同じ書き方で指定できるDocument.querySelector()Document.querySelectorAll()のほうが現在の主流となっています。

複数の要素が存在する場合でもDocument.querySelector()は最初の要素しか取得できないため、複数の要素を取得するときはDocument.querySelectorAll()を使います。

Event.preventDefault()

親要素などのリンクによるページ遷移を無効化します。

まとめ

これまで、新しいWebアプリを作るときは脳死状態で「とりあえず、jQueryとBootstrapを導入して…」としていました。それがあまり健全でない(?)ことだとは感じていましたが、ようやくjQueryを卒業できそうです。

Bootstrapの卒業はまだ時間がかかりそうです…😅

関連記事

【CSS+JS】メニューアイコンの一種、ベントーメニューの実装方法(アニメーション付き)
# はじめに メニューアイコンの中ではハンバーガーメニューが有名だと思いますが、その他にもいろいろな種類があって、それぞれに名前もつけられています。 <a class="gallery" data-group="gallery" href= [...]
2021年10月18日 14:26
【CSS+JS】メインコンテンツの裏から現れるフッターの実装方法
# はじめに オシャレなサイトなどでたまに見かける「メインコンテンツの裏から現れるフッター」の実装方法について説明します。 # サンプル <iframe height="392" style="width: 100%;" scrollin [...]
2021年10月18日 13:26
【CSS+JS】背景画像の視差効果(パララックス)を実装する方法
# はじめに JavaScriptプラグインを使わずに、背景画像の視差効果(パララックス)をVanilla JS(ピュアなJavaScript)だけで実装する方法について説明します。 # サンプル まず、背景画像の視差効果(パララックス) [...]
2021年10月17日 12:08
【CSS+JS】現在のスクロール量を確実に取得する(プロパティ対応状況まとめ)
# はじめに JavaScriptで現在のスクロール量を取得するためのプロパティはたくさんあります。種類がありすぎるため、かえってどれを使えばいいのかいまいちわからないという人も多いかと思います。 本記事では、各プロパティのブラウザ対応状況 [...]
2021年6月5日 15:51
【CSS+JS】ウィンドウ内全体にファイルをドラッグ&ドロップしてアップロード
# はじめに ユーザーが選択したファイルをアップロードする必要がある場合、ファイル選択フィールドを設置することはもちろんですが、ファイルをドラッグ&ドロップしてアップロードできるようにもなっていると使い勝手のいいサービスだと言えます。しかし、ドラ [...]
2021年6月2日 15:15
【CSS+JS】モーダルウィンドウを表示しその中にYouTube動画を動的に埋め込む
# はじめに 動画のサムネイル画像をクリックしてモーダルウィンドウを表示し、その中にYouTube動画を動的に埋め込む方法について説明します。なお、本記事ではYouTube動画を動的に埋め込むまでを範囲とし、埋め込んだ動画の再生制御などは範囲外と [...]
2021年5月20日 23:23
【CSS+JS】テキストを1文字ずつ表示するアニメーションの実装方法
# はじめに モダンなサイトでよく見かける「テキストを1文字ずつ表示するアニメーション」の実装方法を解説します。 # 実装 ## サンプル 繰り返し動作を確認したい場合は右下の「Rerun」ボタンをクリックしてください。 <i [...]
2021年5月20日 13:26
【CSS】CSSカスタムプロパティとJavaScriptを使ってモード切替(配色変更)を実装
# はじめに 便利なCSSカスタムプロパティ。実はJavaScriptから取得/設定ができます。今回はCSSカスタムプロパティとJavaScriptを使ってモード切替(配色変更)を実装する方法を解説します。 # CSSカスタムプロパティ [...]
2020年8月30日 18:07