jQueryを捨てて原生に深く入り込んだJavaScript


今日、私はここ数年で学んだいくつかの基礎的なものをみんなと共有するつもりです.これは純粋なJavaScriptの世界に深く入り込んで、jQueryが次のプロジェクトで必要かどうかをより簡単に決定することができます.
段階的に強化
jQueryのようなライブラリは、多くのブラウザ間の互換性のない問題を解決するのに役立ちますが、純粋なJavaScriptを使用してすべての作業を完了し始めると、確かに彼らに熟知します.ブラウザの修正とブラウザの互換性の問題しか解決できないJavaScriptコードを書くことを避けるために、特徴検出を使用して、より現代的なブラウザだけを目標として、徐々に強化された経験を育成することをお勧めします.これは、IE 7のようなブラウザから何も得られないという意味ではありません.これは、JavaScriptが強化されていない場合に、より基礎的な経験を得たことを示すだけです.
どうやって?
私たちには「feature」というものがあります.js」の分離されたJavaScriptセクションは、すべての機能テストを備えています.実際のテストリストはこれよりずっと長いですが、少し遅れてこの問題に戻りましょう.古いブラウザの互換性を解消するために、次の2つのテストを使用します.
var feature = {
  addEventListener : !!window.addEventListener,
  querySelectorAll : !!document.querySelectorAll,
};

次に、メインアプリケーションセクションでは、これらのプロパティが次の例の簡単なif文でサポートされるかどうかを検出します.サポートされていない場合、ブラウザは次のコードを実行しません.
if (feature.addEventListener && feature.querySelectorAll) {
  this.init();
}

この2つのテストは、JavaScriptでCSSセレクタを使用する場合にローカルメソッド(querySelectorAll)が使用可能であることを保証し、イベントの追加と削除の簡便なメソッド(addEventListener)が使用可能であり、ブラウザ標準サポートはIE 8よりも優れている.この方法の詳細については、BBCブログの「Cutting the mustard」の記事を参照してください.
ブラウザのサポート
この機能をサポートするブラウザをテストし、JavaScriptを実行できる粗いリストを後日保持します.
IE9+
Firefox 3.5+
Opera 9+
Safari 4+
Chrome 1+
iPhone and iPad iOS1+
Android phone and tablets 2.1+
Blackberry OS6+
Windows 7.5+
Mobile Firefox
Opera Mobile
基本オリジナルJavaScriptメソッド
jQueryと比較して、最も基礎的で頻繁な機能が純粋なJavaScriptでどのように機能しているかに注目し始めましょう.各例について、jQueryと純JavaScriptの2つの方法を提供するつもりです.
Document Readyイベント
jQueryでは、あなたたちの多くの人が昔よくdocumentを使っていたかもしれません.ready :
$(document).ready(function() {
  // Code
});

しかし、すべてのJavaScriptをページの下端に置くことができることを知っていますが、彼らは確かに同じことですか?JavaScriptは、jQueryのdocumentではなくDOMコンテンツロードイベントのリスナーを持つ.ready:
document.addEventListener("DOMContentLoaded", function() {
  // Code
}, false);

セレクタAPI
JavaScriptのローカルセレクタAPIは非常に優れています.CSSセレクタに役立ち、jQueryが提供するのと非常に似ています.もしあなたが以前よくjQueryでこのように書いていたら:
var element = $("div");

次の文に置き換えることができます.
var element = document.querySelector("div");

またはdivの一部の内部コンテナを選択します.
var elements = document.querySelectorAll(".container div");

特定の要素に対してクエリーを行い、そのサブ要素を見つけることもできます.
var navigation = document.querySelector("nav");
var links = navigation.querySelectorAll("a");

簡単で、理解しやすく、今はあまりコードが必要ないのではないでしょうか.さらに遠くなると、簡単なDOMクエリーを行うために、小型のJavaScriptライブラリを自分で構築することもできます.以下はAndrew Lunnyが思いついたものです.
// This gives us simple dollar function and event binding
var $ = document.querySelectorAll.bind(document);
Element.prototype.on = Element.prototype.addEventListener;

// This is how you use it
$(".element")[0].on("touchstart", handleTouch, false);

DOMを巡る
純粋なJavaScriptでDOMを巡るのはjQueryを使うより難しいです.しかし、あまり難しくはありません.以下に簡単な例を示します.
// Getting the parent node
var parent = document.querySelector("div").parentNode;
// Getting the next node
var next = document.querySelector("div").nextSibling;
// Getting the previous node
var next = document.querySelector("div").previousSibling;
// Getting the first child element
var child = document.querySelector("div").children[0];
// Getting the last child
var last = document.querySelector("div").lastElementChild;

スタイル名の追加と削除(class name)
jQueryを使用して、要素に特定のクラスがあるかどうかを追加、削除、チェックするのは簡単です.純粋なJavaScriptを使うと少し複雑になりますが、あまり複雑ではありません.要素にfooというクラスを与え、現在のすべてのクラスを置き換えます.
// Select an element
var element = document.querySelector(".some-class");
// Give class "foo" to the element
element.className = "foo";

現在のクラスを置換しないで、クラスを追加します.
element.className += " foo";

html要素から「no-js」クラスを削除し、「js」で置き換えます.
<html class="no-js">
<head>
  <script>
    document.documentElement.className = "js";
  </script>

これはかなり簡単ですね.次に、いくつかのクラスだけを削除するのは少し複雑です.私はずっと単独でこれをutilと呼んでいます.jsの小さなアシスタント関数.要素と削除したいクラスの2つのパラメータがあります.
// removeClass, takes two params: element and classname
function removeClass(el, cls) {
  var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
  el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,"");
}

その後、メインアプリケーションのセクションでは、次のように使用しています.
removeClass(element, "foo");

いくつかのクラスについて同じ要素をチェックしたい場合は、jQueryのhasClassのようにします.これらのコードをutilsツールに追加する必要があります.
// hasClass, takes two params: element and classname
function hasClass(el, cls) {
  return el.className && new RegExp("(\\s|^)" + cls + "(\\s|$)").test(el.className);
}

次のように使用できます.
// Check if an element has class "foo"
if (hasClass(element, "foo")) {

  // Show an alert message if it does
  alert("Element has the class!");
}

HTML 5のclassList APIの概要
IE 10+,Chrome,FireFox,Opera,Safariのような現代的なブラウザをサポートするだけであれば、クラスの追加と削除をより簡単にするためにHTML 5のclassList機能を使用することができます.
これは私が私たちの最新の開発者のドキュメントの中で最終的にしたことです.機能の開発につれて、これはUIの強化に似ています.もしこれが今でなければ、実際には経験を破るものではありません.
次の簡単な「if」文では、ブラウザがこの機能をサポートしているかどうかを検出できます.
if ("classList" in document.documentElement) {
  // classList is supported, now do something with it
}

クラスリストを使用してクラスを追加、削除、変換します.
// Adding a class
element.classList.add("bar");
// Removing a class
element.classList.remove("foo");
// Checking if has a class
element.classList.contains("foo");
// Toggle a class
element.classList.toggle("active");

classListを使用するもう一つの利点は、元のクラス名属性を使用するよりもよく表現されることです.このような要素がある場合は、
<div id="test" class="one two three"></div>

どちらを操作したいですか.
var element = document.querySelector("#test");
addClass(element, "two");
removeClass(element, "four");

これらのクラス名属性の読み取りと書き込み方法は、ブラウザの再描画をトリガーします.しかし、これは私たちが対応するclassListメソッドを使用すべきかどうかではありません.
var element = document.querySelector("#test");
element.classList.add("two");
element.classList.remove("four");

classListを使用した後、最も基本的なクラス名属性は必要に応じてのみ変更されます.既存のクラスを追加し、存在しないクラスを削除すると、クラス名のプロパティにはまったく関与しません.これは、2回の再描画を回避したばかりであることを意味します.
イベントリスナーが要素を追加および削除するイベントリスナーは、純粋なJavaScriptおよびjQueryでも簡単です.複数のイベントリスナーを追加する必要がある場合は、少し複雑になりますが、詳しく説明します.最も簡単な例では、要素をクリックすると、次のコードで説明されている警告メッセージがポップアップされます.
element.addEventListener("click", function() {
  alert("You clicked");
}, false);

この機能をページのすべての要素で実現するには、各要素を順番に繰り返し、イベントリスナーを追加する必要があります.
// Select all links
var links = document.querySelectorAll("a");

// For each link element
[].forEach.call(links, function(el) {

  // Add event listener
  el.addEventListener("click", function(event) {
    event.preventDefault();
    alert("You clicked");
  }, false);

});

JavaScriptのイベントリスナーに関する最も偉大な機能は、「addEventListener」が2番目のパラメータとしてオブジェクトを運ぶことができ、「handleEvent」という方法を自動的に探して呼び出すことです.Ryan Seddonはその文章の中でこの方法を徹底的に紹介したので、私は最も簡単な例をあげるつもりです.あなたはそのブログでもっと多くのことを学ぶことができます.
var object = {
  init: function() {
    button.addEventListener("click", this, false);
    button.addEventListener("touchstart", this, false);
  },
  handleEvent: function(e) {
    switch(e.type) {
      case "click":
        this.action();
        break;
      case "touchstart":
        this.action();
        break;
    }
  },
  action: function() {
    alert("Clicked or touched!");
  }
};

// Init
object.init();

操作DOM
純粋なJavaScriptでDOMを操作するのは最初は恐ろしい考えのように聞こえましたが、jQueryを使うよりも複雑ではありません.次に、DOMの要素を選択してクローンし、JavaScriptでクローンのスタイルを操作し、元の要素の代わりに操作されたものを使用する例を示します.
// Select an element
var element = document.querySelector(".class");

// Clone it
var clone = element.cloneNode(true);

// Do some manipulation off the DOM
clone.style.background = "#000";

// Replaces the original element with the new cloned one
element.parentNode.replaceChild(clone, element);

DOMでは、に添付してdivを新しく作成する以外に、何も置き換えたくない場合は、次のようにすることができます.
document.body.appendChild(clone);

もっと違うDOMの方法を知りたいと思ったら、Peter-Paul KochのDOM Core tablesを読むことをお勧めします.
さらに深く
ここで私が最近発見した先進技術をもっと共有したいです.これらは、Adtileを作成するときに必要な機能なので、役に立つと思います.
JSで応答画像の最大幅を決定する
これは私の大好きな1つで、JavaScriptで流体画像を操作する必要がある場合に便利です.ブラウザは現在サイズを調整されている画像をデフォルトで返すので、他の方法を考えなければなりません.幸いなことに、現代のブラウザには現在解決策があります.
var maxWidth = img.naturalWidth;

これにより、最大幅100%ピクセルの画像が提供され、IE 9、Chrome、Firefox、Safari、Operaがこの方法をサポートします.また、このプロパティを保持し、画像をメモリにロードして古いブラウザのサポートを追加することもできます.
// Get image's max-width:100%; in pixels
function getMaxWidth(img) {
  var maxWidth;

  // Check if naturalWidth is supported
  if (img.naturalWidth !== undefined) {
    maxWidth = img.naturalWidth;

  // Not supported, use in-memory solution as fallback
  } else {
    var image = new Image();
    image.src = img.src;
    maxWidth = image.width;
  }

  // Return the max-width
  return maxWidth;
}

幅をチェックする前に、画像が完全にロードされなければならないことに注意してください.これは、サイズを決定するために使用されてきた方法です.
function hasDimensions(img) {
  return !!((img.complete && typeof img.naturalWidth !== "undefined") || img.width);
}

要素がビューウィンドウにあるかどうかを判断します.
getBoundingClientRectメソッドを使用すると、ページ内の任意の要素の場所を取得できます.以下は、単純さと強さを示す簡単な関数です.この関数にはパラメータがあります.それはあなたがチェックしたい要素です.要素が表示されている場合、関数はtrueを返します.
// Determine if an element is in the visible viewport
function isInViewport(element) {
  var rect = element.getBoundingClientRect();
  var html = document.documentElement;
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || html.clientHeight) &&
    rect.right <= (window.innerWidth || html.clientWidth)
  );
}

上記の関数は、フォームに「スクロール」イベントリスナーを追加し、isInViewport()メソッドを呼び出すときに使用できます.
結論
あなたの次のプロジェクトでjQueryを使用するかどうかは、あなたが構築したプロジェクトに大きく依存します.プロジェクトに大量のフロントエンドコードが必要な場合は、jQueryを使用する必要があります.ただし、JavaScriptプラグインまたはライブラリを構築する場合は、純粋なJavaScriptのみを考慮する必要があります.純粋なJavaScriptを使用することは、より少ないリクエストとより少ないデータロードを意味します.これは、開発者にプロジェクトにjQueryを追加する必要がないことを意味します.