你可能不需要jQuery

You Don't Need jQuery

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

目錄

Translations

Query Selector

CSS & Style

DOM Manipulation

Ajax

Events

Utilities

Promises

Animation

Alternatives

Browser Support

Translations

???

簡體中文

Bahasa Melayu

Bahasa Indonesia

Português(PT-BR)

Ti?ng Vi?t Nam

Espa?ol

Русский

Кыргызча

Türk?e

Italiano

Fran?ais

日本語

Polski

Query Selector

常用的 class、id、屬性 選擇器都可以使用document.querySelector或document.querySelectorAll替代。區別是

document.querySelector返回第一個匹配的 Element

document.querySelectorAll返回所有匹配的 Element 組成的 NodeList。它可以通過[].slice.call()把它轉成 Array

如果匹配不到任何 Element,jQuery 返回空數組[],但document.querySelector返回null,注意空指針異常。當找不到時,也可以使用||設置默認的值,如document.querySelectorAll(selector) || []

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

1.0選擇器查詢

// jQuery$('selector');?// Nativedocument.querySelectorAll('selector');

1.1class 查詢

// jQuery$('.class');?// Nativedocument.querySelectorAll('.class');?// ordocument.getElementsByClassName('class');

1.2id 查詢

// jQuery$('#id');?// Nativedocument.querySelector('#id');?// ordocument.getElementById('id');

1.3屬性查詢

// jQuery$('a[target=_blank]');?// Nativedocument.querySelectorAll('a[target=_blank]');

1.4后代查詢

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

1.5兄弟及上下元素

兄弟元素

// jQuery$el.siblings();?// Native - latest, Edge13+[...el.parentNode.children].filter((child)=>child!==el);// Native (alternative) - latest, Edge13+Array.from(el.parentNode.children).filter((child)=>child!==el);// Native - IE10+Array.prototype.filter.call(el.parentNode.children, (child)=>child!==el);

上一個元素

// jQuery$el.prev();?// Nativeel.previousElementSibling;

下一個元素

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

1.6Closest

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

// jQuery$el.closest(queryString);?// Native - Only latest, NO IEel.closest(selector);?// Native - IE10+functionclosest(el,selector) {constmatchesSelector=el.matches||el.webkitMatchesSelector||el.mozMatchesSelector||el.msMatchesSelector;?while(el) {if(matchesSelector.call(el,selector)) {returnel;}else{el=el.parentElement;}}returnnull;}

1.7Parents Until

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

// jQuery$el.parentsUntil(selector,filter);?// NativefunctionparentsUntil(el,selector,filter) {constresult=[];constmatchesSelector=el.matches||el.webkitMatchesSelector||el.mozMatchesSelector||el.msMatchesSelector;?// match start from parentel=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;}returnresult;}

1.8Form

Input/Textarea

// jQuery$('#my-input').val();?// Nativedocument.querySelector('#my-input').value;

獲取 e.currentTarget 在.radio中的數組索引

// jQuery$('.radio').index(e.currentTarget);?// NativeArray.prototype.indexOf.call(document.querySelectorAll('.radio'),e.currentTarget);

1.9Iframe Contents

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

Iframe contents

// jQuery$iframe.contents();?// Nativeiframe.contentDocument;

Iframe Query

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

1.10獲取 body

// jQuery$('body');?// Nativedocument.body;

1.11獲取或設置屬性

獲取屬性

// jQuery$el.attr('foo');?// Nativeel.getAttribute('foo');

設置屬性

// jQuery, note that this works in memory without change the DOM$el.attr('foo','bar');?// Nativeel.setAttribute('foo','bar');

獲取data-屬性

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

? 回到頂部

CSS & Style

2.1CSS

Get style

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

Set style

// jQuery$el.css({color:"#ff0011"});?// Nativeel.style.color='#ff0011';

Get/Set Styles

注意,如果想一次設置多個 style,可以參考 oui-dom-utils 中setStyles方法

Add class

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

Remove class

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

has class

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

Toggle class

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

2.2Width & Height

Width 與 Height 獲取方法相同,下面以 Height 為例:

Window height

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

Document height

// jQuery$(document).height();?// Nativeconstbody=document.body;consthtml=document.documentElement;constheight=Math.max(body.offsetHeight,body.scrollHeight,html.clientHeight,html.offsetHeight,html.scrollHeight);

Element height

// jQuery$el.height();?// NativefunctiongetHeight(el) {conststyles=this.getComputedStyle(el);constheight=el.offsetHeight;constborderTopWidth=parseFloat(styles.borderTopWidth);constborderBottomWidth=parseFloat(styles.borderBottomWidth);constpaddingTop=parseFloat(styles.paddingTop);constpaddingBottom=parseFloat(styles.paddingBottom);returnheight-borderBottomWidth-borderTopWidth-paddingTop-paddingBottom;}?// 精確到整數(border-box 時為 height - border 值,content-box 時為 height + padding 值)el.clientHeight;?// 精確到小數(border-box 時為 height 值,content-box 時為 height + padding + border 值)el.getBoundingClientRect().height;

2.3Position & Offset

Position

獲得匹配元素相對父元素的偏移

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

Offset

獲得匹配元素相對文檔的偏移

// jQuery$el.offset();?// NativefunctiongetOffset(el) {constbox=el.getBoundingClientRect();?return{top:box.top+window.pageYOffset-document.documentElement.clientTop,left:box.left+window.pageXOffset-document.documentElement.clientLeft}}

2.4Scroll Top

獲取元素滾動條垂直位置。

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

? 回到頂部

DOM Manipulation

3.1Remove

從 DOM 中移除元素。

// jQuery$el.remove();?// Nativeel.parentNode.removeChild(el);

3.2Text

Get text

返回指定元素及其后代的文本內容。

// jQuery$el.text();?// Nativeel.textContent;

Set text

設置元素的文本內容。

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

3.3HTML

Get HTML

// jQuery$el.html();?// Nativeel.innerHTML;

Set HTML

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

3.4Append

Append 插入到子節點的末尾

// jQuery$el.append("

hello
");?// Native (HTML string)el.insertAdjacentHTML('beforeend','
Hello World
');?// Native (Element)el.appendChild(newEl);

3.5Prepend

// jQuery$el.prepend("

hello
");?// Native (HTML string)el.insertAdjacentHTML('afterbegin','
Hello World
');?// Native (Element)el.insertBefore(newEl,el.firstChild);

3.6insertBefore

在選中元素前插入新節點

// jQuery$newEl.insertBefore(queryString);?// Native (HTML string)el.insertAdjacentHTML('beforebegin ','

Hello World
');?// Native (Element)constel=document.querySelector(selector);if(el.parentNode) {el.parentNode.insertBefore(newEl,el);}

3.7insertAfter

在選中元素后插入新節點

// jQuery$newEl.insertAfter(queryString);?// Native (HTML string)el.insertAdjacentHTML('afterend','

Hello World
');?// Native (Element)constel=document.querySelector(selector);if(el.parentNode) {el.parentNode.insertBefore(newEl,el.nextSibling);}

3.8is

如果匹配給定的選擇器,返回true

// jQuery$el.is(selector);?// Nativeel.matches(selector);

3.9clone

深拷貝被選元素。(生成被選元素的副本,包含子節點、文本和屬性。)

//jQuery$el.clone();?//Nativeel.cloneNode();

//深拷貝添加參數‘true’```

3.10empty

移除所有子節點

//jQuery$el.empty();?//Nativeel.innerHTML='';

3.11wrap

把每個被選元素放置在指定的HTML結構中。

//jQuery$(".inner").wrap('

');?//NativeArray.prototype.forEach.call(document.querySelector('.inner'), (el)=>{constwrapper=document.createElement('div');wrapper.className='wrapper';el.parentNode.insertBefore(wrapper,el);el.parentNode.removeChild(el);wrapper.appendChild(el);});

3.12unwrap

把被選元素的父元素移除DOM結構

// jQuery$('.inner').unwrap();?// NativeArray.prototype.forEach.call(document.querySelectorAll('.inner'), (el)=>{Array.prototype.forEach.call(el.childNodes, (child)=>{el.parentNode.insertBefore(child,el);});el.parentNode.removeChild(el);});

3.13replaceWith

用指定的元素替換被選的元素

//jQuery$('.inner').replaceWith('

');?//NativeArray.prototype.forEach.call(document.querySelectorAll('.inner'),(el)=>{constouter=document.createElement("div");outer.className="outer";el.parentNode.insertBefore(outer,el);el.parentNode.removeChild(el);});

3.14simple parse

解析 HTML/SVG/XML 字符串

// jQuery$(`

  1. a
  2. b
  1. c
  2. d
`);?// Nativerange=document.createRange();parse=range.createContextualFragment.bind(range);?parse(`
  1. a
  2. b
  1. c
  2. d
`);

? 回到頂部

Ajax

Fetch API是用于替換 XMLHttpRequest 處理 ajax 的新標準,Chrome 和 Firefox 均支持,舊瀏覽器可以使用 polyfills 提供支持。

IE9+ 請使用github/fetch,IE8+ 請使用fetch-ie8,JSONP 請使用fetch-jsonp

4.1從服務器讀取數據并替換匹配元素的內容。

// jQuery$(selector).load(url,completeCallback)?// Nativefetch(url).then(data=>data.text()).then(data=>{document.querySelector(selector).innerHTML=data}).then(completeCallback)

? 回到頂部

Events

完整地替代命名空間和事件代理,鏈接到https://github.com/oneuijs/oui-dom-events

5.0Document ready byDOMContentLoaded

// jQuery$(document).ready(eventHandler);?// Native// 檢測 DOMContentLoaded 是否已完成if(document.readyState==='complete'||document.readyState!=='loading') {eventHandler();}else{document.addEventListener('DOMContentLoaded',eventHandler);}

5.1使用 on 綁定事件

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

5.2使用 off 解綁事件

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

5.3Trigger

// jQuery$(el).trigger('custom-event', {key1:'data'});?// Nativeif(window.CustomEvent) {constevent=newCustomEvent('custom-event', {detail: {key1:'data'}});}else{constevent=document.createEvent('CustomEvent');event.initCustomEvent('custom-event',true,true, {key1:'data'});}?el.dispatchEvent(event);

? 回到頂部

Utilities

大部分實用工具都能在 native API 中找到. 其他高級功能可以選用專注于該領域的穩定性和性能都更好的庫來代替,推薦lodash

6.1基本工具

isArray

檢測參數是不是數組。

// jQuery$.isArray(range);?// NativeArray.isArray(range);

isWindow

檢測參數是不是 window。

// jQuery$.isWindow(obj);?// NativefunctionisWindow(obj) {returnobj!==null&&obj!==undefined&&obj===obj.window;}

inArray

在數組中搜索指定值并返回索引 (找不到則返回 -1)。

// jQuery$.inArray(item,array);?// Nativearray.indexOf(item)>-1;?// ES6-wayarray.includes(item);

isNumeric

檢測傳入的參數是不是數字。Usetypeofto decide the type or thetypeexample for better accuracy.

// jQuery$.isNumeric(item);?// NativefunctionisNumeric(value) {vartype=typeofvalue;?return(type==='number'||type==='string')&&!Number.isNaN(value-Number.parseFloat(value));}

isFunction

檢測傳入的參數是不是 JavaScript 函數對象。

// jQuery$.isFunction(item);?// NativefunctionisFunction(item) {if(typeofitem==='function') {returntrue;}vartype=Object.prototype.toString(item);returntype==='[object Function]'||type==='[object GeneratorFunction]';}

isEmptyObject

檢測對象是否為空 (包括不可枚舉屬性).

// jQuery$.isEmptyObject(obj);?// NativefunctionisEmptyObject(obj) {returnObject.keys(obj).length===0;}

isPlainObject

檢測是不是扁平對象 (使用 “{}” 或 “new Object” 創建).

// jQuery$.isPlainObject(obj);?// NativefunctionisPlainObject(obj) {if(typeof(obj)!=='object'||obj.nodeType||obj!==null&&obj!==undefined&&obj===obj.window) {returnfalse;}?if(obj.constructor&&!Object.prototype.hasOwnProperty.call(obj.constructor.prototype,'isPrototypeOf')) {returnfalse;}?returntrue;}

extend

合并多個對象的內容到第一個對象。object.assign 是 ES6 API,也可以使用polyfill

// jQuery$.extend({},defaultOpts,opts);?// NativeObject.assign({},defaultOpts,opts);

trim

移除字符串頭尾空白。

// jQuery$.trim(string);?// Nativestring.trim();

map

將數組或對象轉化為包含新內容的數組。

// jQuery$.map(array, (value,index)=>{});?// Nativearray.map((value,index)=>{});

each

輪詢函數,可用于平滑的輪詢對象和數組。

// jQuery$.each(array, (index,value)=>{});?// Nativearray.forEach((value,index)=>{});

grep

找到數組中符合過濾函數的元素。

// jQuery$.grep(array, (value,index)=>{});?// Nativearray.filter((value,index)=>{});

type

檢測對象的 JavaScript [Class] 內部類型。

// jQuery$.type(obj);?// Nativefunctiontype(item) {constreTypeOf=/(?:^\[object\s(.*?)\]$)/;returnObject.prototype.toString.call(item).replace(reTypeOf,'$1').toLowerCase();}

merge

合并第二個數組內容到第一個數組。

// jQuery$.merge(array1,array2);?// Native// But concat function doesn't remove duplicate items.functionmerge(...args) {return[].concat(...args)}

now

返回當前時間的數字呈現。

// jQuery$.now();?// NativeDate.now();

proxy

傳入函數并返回一個新函數,該函數綁定指定上下文。

// jQuery$.proxy(fn,context);?// Nativefn.bind(context);

makeArray

類數組對象轉化為真正的 JavaScript 數組。

// jQuery$.makeArray(arrayLike);?// NativeArray.prototype.slice.call(arrayLike);?// ES6-wayArray.from(arrayLike);

6.2包含

檢測 DOM 元素是不是其他 DOM 元素的后代.

// jQuery$.contains(el,child);?// Nativeel!==child&&el.contains(child);

6.3Globaleval

全局執行 JavaScript 代碼。

// jQuery$.globaleval(code);?// NativefunctionGlobaleval(code) {constscript=document.createElement('script');script.text=code;?document.head.appendChild(script).parentNode.removeChild(script);}?// Use eval, but context of eval is current, context of $.Globaleval is global.eval(code);

6.4解析

parseHTML

解析字符串為 DOM 節點數組.

// jQuery$.parseHTML(htmlString);?// NativefunctionparseHTML(string) {constcontext=document.implementation.createHTMLDocument();?// Set the base href for the created document so any parsed elements with URLs// are based on the document's URLconstbase=context.createElement('base');base.href=document.location.href;context.head.appendChild(base);?context.body.innerHTML=string;returncontext.body.children;}

parseJSON

傳入格式正確的 JSON 字符串并返回 JavaScript 值.

// jQuery$.parseJSON(str);?// NativeJSON.parse(str);

? 回到頂部

Promises

Promise 代表異步操作的最終結果。jQuery 用它自己的方式處理 promises,原生 JavaScript 遵循Promises/A+標準實現了最小 API 來處理 promises。

7.1done, fail, always

done會在 promise 解決時調用,fail會在 promise 拒絕時調用,always總會調用。

// jQuery$promise.done(doneCallback).fail(failCallback).always(alwaysCallback)?// Nativepromise.then(doneCallback,failCallback).then(alwaysCallback,alwaysCallback)

7.2when

when用于處理多個 promises。當全部 promises 被解決時返回,當任一 promise 被拒絕時拒絕。

// jQuery$.when($promise1,$promise2).done((promise1Result,promise2Result)=>{});?// NativePromise.all([$promise1,$promise2]).then([promise1Result,promise2Result]=>{});

7.3Deferred

Deferred 是創建 promises 的一種方式。

// jQueryfunctionasyncFunc() {constdefer=new$.Deferred();setTimeout(()=>{if(true) {defer.resolve('some_value_computed_asynchronously');}else{defer.reject('failed');}},1000);?returndefer.promise();}?// NativefunctionasyncFunc() {returnnewPromise((resolve,reject)=>{setTimeout(()=>{if(true) {resolve('some_value_computed_asynchronously');}else{reject('failed');}},1000);});}?// Deferred wayfunctiondefer() {constdeferred={};constpromise=newPromise((resolve,reject)=>{deferred.resolve=resolve;deferred.reject=reject;});?deferred.promise=()=>{returnpromise;};?returndeferred;}?functionasyncFunc() {constdefer=defer();setTimeout(()=>{if(true) {defer.resolve('some_value_computed_asynchronously');}else{defer.reject('failed');}},1000);?returndefer.promise();}

? 回到頂部

Animation

8.1Show & Hide

// jQuery$el.show();$el.hide();?// Native// 更多 show 方法的細節詳見 https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L363el.style.display=''|'inline'|'inline-block'|'inline-table'|'block';el.style.display='none';

8.2Toggle

顯示或隱藏元素。

// jQuery$el.toggle();?// Nativeif(el.ownerDocument.defaultView.getComputedStyle(el,null).display==='none') {el.style.display=''|'inline'|'inline-block'|'inline-table'|'block';}else{el.style.display='none';}

8.3FadeIn & FadeOut

// jQuery$el.fadeIn(3000);$el.fadeOut(3000);?// Nativeel.style.transition='opacity 3s';// fadeInel.style.opacity='1';// fadeOutel.style.opacity='0';

8.4FadeTo

調整元素透明度。

// jQuery$el.fadeTo('slow',0.15);// Nativeel.style.transition='opacity 3s';// 假設 'slow' 等于 3 秒el.style.opacity='0.15';

8.5FadeToggle

動畫調整透明度用來顯示或隱藏。

// jQuery$el.fadeToggle();?// Nativeel.style.transition='opacity 3s';const{opacity}=el.ownerDocument.defaultView.getComputedStyle(el,null);if(opacity==='1') {el.style.opacity='0';}else{el.style.opacity='1';}

8.6SlideUp & SlideDown

// jQuery$el.slideUp();$el.slideDown();?// NativeconstoriginHeight='100px';el.style.transition='height 3s';// slideUpel.style.height='0px';// slideDownel.style.height=originHeight;

8.7SlideToggle

滑動切換顯示或隱藏。

// jQuery$el.slideToggle();?// NativeconstoriginHeight='100px';el.style.transition='height 3s';const{height}=el.ownerDocument.defaultView.getComputedStyle(el,null);if(parseInt(height,10)===0) {el.style.height=originHeight;}else{el.style.height='0px';}

8.8Animate

執行一系列 CSS 屬性動畫。

// jQuery$el.animate({params},speed);?// Nativeel.style.transition='all '+speed;Object.keys(params).forEach((key)=>el.style[key]=params[key];)

? 回到頂部

Alternatives

你可能不需要 jQuery (You Might Not Need jQuery)- 如何使用原生 JavaScript 實現通用事件,元素,ajax 等用法。

npm-dom以及webmodules- 在 NPM 上提供獨立 DOM 模塊的組織

Browser Support

Latest ?Latest ?10+ ?Latest ?6.1+ ?

License

MIT

chrome-imagehttps://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png

firefox-imagehttps://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png

ie-imagehttps://raw.github.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png

opera-imagehttps://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png

safari-imagehttps://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容