You Don't Need jQuery

這是一篇使用原生JavaScript代替jQuery實踐的文章, GitHub 原文

      前端發展很快,現代瀏覽器原生 API 已經足夠好用。我們並不需要爲了操作 DOM、Event 等再學習一下 jQuery 的 API。同時由於 React、Angular、Vue  
等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用場景大大減少。本項目總結了大部分 jQuery API 替代的方法,暫時只支持 IE10+ 以上瀏覽器。

1.Query Selector

      常用的 class、id、屬性 選擇器都可以使用 document.querySelector或 document.querySelectorAll
 替代。區別是
document.querySelector   返回第一個匹配的 Element
document.querySelectorAll
  返回所有匹配的 Element 組成的 NodeList。它可以通過  [].slice.call() 把它轉成 Array
  如果匹配不到任何 Element,jQuery 返回空數組  [],但 document.querySelector返回  nul ,注意空指針異常。當找不到時,
也可以使用  ||設置默認的值,如  document.querySelectorAll(selector) || []

注意: document.querySelector
 和  document.querySelectorAll
 性能很差。如果想提高性能,儘量使用 
    document.getElementById
 、document.getElementsByClassName
 或  document.getElementsByTagName
 。

1.0  Query by selector

// jQuery
$('selector');
// Native
document.querySelectorAll('selector');

1.1  Query by class

// jQuery
$('.css');
// Native
document.querySelectorAll('.css');
// or
document.getElementsByClassName('css');

1.2 Query by id 

// jQuery
$('#id');
// Native
document.querySelector('#id');
// or
document.getElementById('id');

1.3 Query by attribute 

// jQuery
$('a[target=_blank]');
// Native
document.querySelectorAll('a[target=_blank]');

1.4  Find sth.
Find nodes

// jQuery
$el.find('li');
// Native
el.querySelectorAll('li');

Find body

// jQuery
$('body');
// Native
document.body;

Find Attribute

// jQuery
$el.attr('foo');
// Native
e.getAttribute('foo');

Find data attribute

// jQuery
$el.data('foo');
// Native
// using getAttribute
el.getAttribute('data-foo');
// you can also use `dataset` if only need to support IE 11+
el.dataset['foo'];

1.5 Sibling/Previous/Next Elements 
Sibling elements

// jQuery
$el.siblings();
// Native
[].filter.call(el.parentNode.children, function(child)
 { return child !== el;});

Previous elements

// jQuery
$el.prev();
// Native
el.previousElementSibling;

Next elements

// next
$el.next();
el.nextElementSibling;

1.6  Closest
Closest 獲得匹配選擇器的第一個祖先元素,從當前元素開始沿 DOM 樹向上。

// jQuery
$el.closest(queryString);
// Native
function closest(el, selector) 
{ const matchesSelector = el.matches || el.webkitMatchesSelector 
|| el.mozMatchesSelector || el.msMatchesSelector;
 while (el)
 { 
if (matchesSelector.call(el, selector))
 { return el; }
 else
 { el = el.parentElement; } } 
return null;
}

1.7  Parents Until
獲取當前每一個匹配元素集的祖先,不包括匹配元素的本身。

// jQuery
$el.parentsUntil(selector, filter);
// Native
function parentsUntil(el, selector, filter)
 { const result = []; const matchesSelector = el.matches || 
el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
 // match start from parent 
el = el.parentElement; 
while (el && !matchesSelector.call(el, selector))
 { 
    if (!filter) { 
        result.push(el);
     }
     else {
         if (matchesSelector.call(el, filter)) { result.push(el); } } 
         el = el.parentElement;
     }
 return result;
}

1.8 Form 
Input/Textarea

// jQuery
$('#my-input').val();
// Native
document.querySelector('#my-input').value;

Get index of e.currentTarget between .radio

// jQuery
$(e.currentTarget).index('.radio');
// Native
[].indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);

1.9  Iframe Contents

jQuery 對象的 iframe contents() 返回的是 iframe 內的  document

Iframe contents

// jQuery
$iframe.contents();
// Native
iframe.contentDocument;

Iframe Query

// jQuery
$iframe.contents().find('.css');
// Native
iframe.contentDocument.querySelectorAll('.css');

CSS & Style

2.1  CSS Get style

// jQuery
$el.css("color");
// Native
// 注意:此處爲了解決當 style 值爲 auto 時,返回 auto 的問題
const win = el.ownerDocument.defaultView;
// null 的意思是不返回僞類元素
win.getComputedStyle(el, null).color;

Set style
““
// jQuery
$el.css({ color: “#ff0011” });
// Native
el.style.color = ‘#ff0011’;

Get/Set Styles
注意,如果想一次設置多個 style,可以參考 oui-dom-utils 中 [setStyles](https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L194) 方法

Add class

// jQuery
$el.addClass(className);
// Native
el.classList.add(className);

Remove class

// jQuery
$el.removeClass(className);
// Native
el.classList.remove(className);

has class

// jQuery
$el.hasClass(className);
// Native
el.classList.contains(className);

Toggle class

// jQuery
$el.toggleClass(className);
// Native
el.classList.toggle(className);

[2.2 Width & Height](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#2.2) 
Width 與 Height 獲取方法相同,下面以 Height 爲例:
Window height

// jQuery
$(window).height();
// Native
// 不含 scrollbar,與 jQuery 行爲一致
window.document.documentElement.clientHeight;
// 含
scrollbarwindow.innerHeight;

Document height

// jQuery
$(document).height();
// Native
document.documentElement.scrollHeight;

Element height

// jQuery
$el.height();
// Native// 與 jQuery 一致(一直爲 content 區域的高度)
function getHeight(el)
{
const styles = this.getComputedStyles(el);
const height = el.offsetHeight;
const borderTopWidth = parseFloat(styles.borderTopWidth);
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
const paddingTop = parseFloat(styles.paddingTop);
const paddingBottom = parseFloat(styles.paddingBottom);
return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}
// 精確到整數(border-box 時爲 height 值,content-box 時爲 height + padding + border 值)el.clientHeight;
// 精確到小數(border-box 時爲 height 值,content-box 時爲 height + padding + border 值)el.getBoundingClientRect().height;

Iframe height

iframe.contents()iframecontentDocument//jQuery (‘iframe’).contents().height();
// Native
iframe.contentDocument.documentElement.scrollHeight;

[2.3 Position & Offset](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#2.3) 

Position

// jQuery
$el.position();
// Native
{ left: el.offsetLeft, top: el.offsetTop }

Offset

// jQuery
$el.offset();
// Native
function getOffset (el)
{
const box = el.getBoundingClientRect();

return { top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}}

[2.4 Scroll Top](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#2.4

// jQuery
$(window).scrollTop();
// Native
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;

#DOM Manipulation

[3.1  Remove](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.1

// jQuery
$el.remove();
// Native
el.parentNode.removeChild(el);

[3.2 Text Get text](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.2

// jQuery
$el.text();
// Native
el.textContent;

Set text

// jQuery
$el.text(string);
// Native
el.textContent = string;

[3.3  HTML](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.3) 
Get HTML

// jQuery
$el.html();
// Native
el.innerHTML;

Set HTML

// jQuery
$el.html(htmlString);
// Native
el.innerHTML = htmlString;

[3.4 Append](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.4) 
Append 插入到子節點的末尾

// jQuery
$el.append(“

hello
“);
// Native
let newEl = document.createElement(‘div’);
newEl.setAttribute(‘id’, ‘container’);
newEl.innerHTML = ‘hello’;el.appendChild(newEl);

[3.5 Prepend](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.5

// jQuery
$el.prepend(“

hello
“);
// Native
let newEl = document.createElement(‘div’);
newEl.setAttribute(‘id’, ‘container’);
newEl.innerHTML = ‘hello’;
el.insertBefore(newEl, el.firstChild);

[3.6 insertBefore](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.6) 
在選中元素前插入新節點

// jQuery
$newEl.insertBefore(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target);

[3.7 insertAfter](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#3.7) 
在選中元素後插入新節點

// jQuery
$newEl.insertAfter(queryString);
// Native
const target = document.querySelector(queryString);
target.parentNode.insertBefore(newEl, target.nextSibling);

Ajax
用 [fetch](https://github.com/camsong/fetch-ie8) 和  [fetch-jsonp](https://github.com/camsong/fetch-jsonp) 替代
Events
完整地替代命名空間和事件代理,鏈接到 [https://github.com/oneuijs/oui-dom-events](https://github.com/oneuijs/oui-dom-events)
[5.1 Bind an event with on](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#5.1

// jQuery
$el.on(eventName, eventHandler);
// Native
el.addEventListener(eventName, eventHandler);

[5.2 Unbind an event with off](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#5.2

// jQuery
$el.off(eventName, eventHandler);
// Native
el.removeEventListener(eventName, eventHandler);

[5.3 Trigger](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#5.3

// jQuery
$(el).trigger(‘custom-event’, {key1: ‘data’});
// Native
if (window.CustomEvent) { const event = new CustomEvent(‘custom-event’,
{detail: {key1: ‘data’}});}
else { const event = document.createEvent(‘CustomEvent’);
event.initCustomEvent(‘custom-event’, true, true, {key1: ‘data’});
}
el.dispatchEvent(event);

#Utilities
[6.1 isArray](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#6.1

// jQuery
$.isArray(range);
// Native
Array.isArray(range);

[6.2 Trim](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#6.2

// jQuery
$.trim(string);
// Native
string.trim();

[6.3 Object Assign](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#6.3) 
繼承,使用 object.assign polyfill [https://github.com/ljharb/object.assign](https://github.com/ljharb/object.assign)

// jQuery
$.extend({}, defaultOpts, opts);
// Native
Object.assign({}, defaultOpts, opts);

[6.4 Contains](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#6.4

// jQuery
$.contains(el, child);
// Native
el !== child && el.contains(child);
“`

Alternatives

你可能不需要 jQuery (You Might Not Need jQuery)  - 如何使用原生 JavaScript 實現通用事件,元素,ajax 等用法。
npm-dom  以及  webmodules  - 在 NPM 上提供獨立 DOM 模塊的組織

發佈了33 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章