jQueryへのjfactorのリファクタリング

27365 ワード

カバー写真Markus Spiske on Unsplash

jQueryの歴史をちょっと見てみる

The big bang of web development


2006年から2015年の間に、jQueryは革命的でした.これは、開発者が苦労していたすべてのライブラリのコードを維持していた:標準化されたAPIは、HTMLの要素を選択し、クロスブラウザのサポート.
今2020では、読者として、これらの機能をいじる可能性があります.しかし、これはECMAScript 6(ES 6)の外観の前にフロントエンドのWeb開発者のための現実であり、CSS 3の他の重要な機能は、当然のために取ることができる.

依存性としてjQueryを削除する理由

Over-reliance can be an addiction


依存関係は悪いことではありません、開発者がゼロからすべてをコード化する必要はありません、そして、毎回「車輪を再発明してください」.しかし、jQueryのほとんどの用法は、バニラJavaScriptで達成するのに些細なものであり、JQueryライブラリ全体をクライアントのブラウザにインポートする必要はないと主張します.言い換えると、我々はこの依存性を削除して、負荷速度を増加させ、できればネイティブのブラウザ機能を使用するようにしたいかもしれません.

デモコード

Lead by example


だから今日、私はどのように私はいくつかのjQuery関数をリファクタリングから私のHypeTracker バニラJavaScriptにプロジェクト.
// private/js/ajax.js
// run functions after document has loaded
$('document').ready(function() {
    // ajax update shown products after select value changes
    $('#brand').change(function() {
        var brand_id = $(this).val();
        $.ajax({
            url: "./load_data.php",
            method: "POST",
            data: {brand_id : brand_id},
            success: function (data) {
                $('#show_product').html(data);
            }
        });
    });

    // update view if user enters characters into search box
    $('#sneaker_search').unbind().keyup(function(e) {
        var value = $(this).val();
        if (value.length >= 1) {
            search_sneaker(value);
        } else {
            $('#search_result').hide();
            $('#show_product').show();
        }
    });

    // ajax post call to return search results from search box
    function search_sneaker(val) {
        $('#show_product').hide();
        $('#search_result').show();
        $.post('./load_data.php', {
            'search_data' : val
        }, function(data) {
            if (data != "") {
                $('#search_result').html(data);
            } else {
                // default view if no results
                $('#search_result').html("<div class=\"row pl-3\"><div class=\"col-3\">No Result Found...</div></div>");
            }
        });
    }
});
私は前もって謝罪します、コードが偉大でないので、しかし、それは数年前も書かれました、そして、私はより良いコードを書くことを学びました.私がこのコードを使用している理由は、コントラクトのある実例からのコードであり、JQueryの代わりに使用する正確なJavaScript関数を伝えるリソースです.

コードを壊す

Making it bite-sized


どんなプロジェクトと同様に、私は自分自身を書いた古いものでも、最初のことは何かを理解しているかを達成しようとしている.コードを読んで、それぞれのセクションの要点を一覧表示しました.
  • IDを持つSelect要素の値のときにイベントが呼び出されますbrand 変化
  • イベント: AJAXを送信するPOST リクエストload_data.php を返します.show_product
  • IDを持つ入力フィールドのときにイベントが呼び出されますsneaker_search とフォーカスされ、検出されたキーボードからのキーがリリースされます
  • それはsearch_sneaker 入力フィールドに文字が検出された場合の関数
  • そうでなければ、要素show_product と要素を隠すsearch_result
  • 機能search_sneaker AJAXを送信するPOST リクエストload_data.php を返します.search_result
  • 上記のすべてはヘルパー機能の中で包まれ、ドキュメントが完全にロードされるまで全てのコードが実行されないようにします

  • 1つずつ変更に取り組む

    Baby steps, one at a time


    まず始めに、Ajaxリクエストを抽出します.あなたが気づいていないならば、私が私が述べた所の上で私の内訳の2つの例がありますPOST リクエストload_data.php これは、私がドライ(自分自身を繰り返さない)原理に違反していることを意味し、再利用可能な関数にリファクタすることができます.

    非同期JavaScriptとXML
    jQueryの強力な提案は、ネイティブの上のその合理化されたAJAX要求と応答機能でしたXMLHttpRequest . しかし、その導入fetch API あまりにも使いやすいので、これを変更し、約束ベースの構文をサポートしています.最後のポイントはさらに良いときにIEをサポートする必要はありませんてthe introduction of the async / await keywords in the browser .
    私は誰もサポートしていないので、本当に、私はフェッチAPIとasync / await Ajax関数を作成するには.
    最初に、jqueryのためのfetch等価物を使用します$post(url, data) , はfetch(url, { method: 'POST'}) .
    次に、2つの方法でデータをエンコードできます.
  • 手動でそれをエンコードします.field1=data1&field2=data2 )
  • 使用する FormData interface それをする
  • 使用FormData インターフェース、私たちはこのような新しい機能で終わります:
    async function searchSneaker(type, value) {
    
      let searchData = new FormData();
      searchData.append(type, value);
    
      const response = await fetch('./load_data.php', {
        method: 'POST',
        body: searchData
      });
    
      if (!response.ok) {
        throw new Error(response.status);
      }
    
      const text = await response.text();
      return text;
    }
    
    クイック側の注意として、取得約束オブジェクトは、デフォルトで悪いHTTPステータスにエラーを投げません.代わりに、Promiseオブジェクトのok プロパティはtrue(HTTPステータスコード200 - 299)か、手動でstatus プロパティ.

    要素セレクタ
    第2の部分は比較的短いです、しかし、それは我々がJavaScript変数で我々のセレクタを統合するのを援助します.
    jQueryでは、$(element) 関数.一方、バニラJavaScriptはquerySelector and getElementById . 構文を切り替えて、上から必要とされる要素を特定します.
    const products = document.getElementById('show_product');
    const searchResult = document.getElementById('search_result');
    const searchBox = document.getElementById('sneaker_search');
    const brandSelector = document.getElementById('brand');
    

    イベントリスナー
    リファクタリングを終了する最終的な手順はevent listeners . jQueryでは、次のようなイベントリスナーと一緒に要素セレクタをチェインしました$(element).on(...) or $(element).change(...) . ネイティブイベントリスナーインターフェイスは、引数としてイベントの型を指定すること以外にはあまり異なりません.
    document.onreadystatechange = function () {
      if (document.readyState === 'complete') {
        searchBox.addEventListener('input', filterBySearch);
        brandSelector.addEventListener('change', filterByBrand);
      }
    }
    
    The filterBySearch and filterByBrand 変数は実際に引数として渡される関数です.この場合、対応する関数はEvent パラメータとしてのオブジェクト.このコードのチャンクは、その時点でイベントリスナーを添付することでドキュメントが完全に読み込まれるまで、AJAX機能が送られないように注意します.

    完成したコード

    Glad you made it this far


    これらの3つのカテゴリの変更を行い、JSDOCスタイルのコメントを使用した後、次のようにコードを終了しました.
    const products = document.getElementById('show_product');
    const searchResult = document.getElementById('search_result');
    const searchBox = document.getElementById('sneaker_search');
    const brandSelector = document.getElementById('brand');
    
    document.onreadystatechange = function () {
      if (document.readyState === 'complete') {
        searchBox.addEventListener('input', filterBySearch);
        brandSelector.addEventListener('change', filterByBrand);
      }
    }
    
    /*
     * Limit Products by Brand Select
     *
     * @param {Event} brand - value from select event
     * @return {void} updates product html
     *
     */
    async function filterByBrand(brand) {
      brandId = brand.target.value;
      const sneakers = await searchSneaker('brand_id', brandId);
      if (sneakers === null) return;
      products.innerHTML = sneakers;
    }
    
    /*
     * Limit Products by Search Phrase
     *
     * @param {Event} search - value from input event
     * @return {void} updates search result html
     *
     */
    async function filterBySearch(search) {
    
      let searchValue = search.target.value;
    
      if (searchValue.length <= 0) {
        searchResult.style.display = 'none';
        products.style.display = 'block';
        return;
      }
    
      const sneakers = await searchSneaker('search_data', searchValue);
    
      if (sneakers !== "") {
        searchResult.innerHTML = sneakers;
        return;
      }
    
      searchResult.innerHTML = "<div class=\"row pl-3\"><div class=\"col-3\">No Result Found...</div></div>";
    }
    
    /*
     * Send an async request with search term
     *
     * @param {string} type - search type
     * @param {string} value - search value
     * @return {text} the formatted HTML with data
     *
     */
    async function searchSneaker(type, value) {
    
      let searchData = new FormData();
      searchData.append(type, value);
    
      const response = await fetch('./load_data.php', {
        method: 'POST',
        body: searchData
      });
    
      if (!response.ok) {
        throw new Error(response.status);
      }
    
      const text = await response.text();
      return text;
    }
    
    説明を省略したfilterByBrand and filterBySearch 関数は基本的なJavaScriptからです.最後の注意事項はinnerHTML プロパティはhtml jQueryでのプロパティー.

    ラッピング
    私は、あなたがより良いコードを書くことができるか、jQueryからネイティブのJavaScriptに変換するのがかなり簡単であるかどうかに関係なく、あなたがこのコードをリファクタリングする私のプロセスについて読んで何かを学んだことを望みました.
    あなたがまだ混乱したならば、私は参照と更なる読書のために若干の関連を残します.
    Twitterやハッピーコーディングで私と接続すること自由に感じなさい!

    資源
    History of JQuery
    You Might Not Need JQuery
    Essential Cheatsheet: Convert JQuery to Javascript
    How to use fetch with async / await