You Don't Need jQuery
前端发展很快,现代浏览器原生 API 已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用场景大大减少。本项目总结了大部分 jQuery API 替代的方法,暂时只支持 IE10 以上浏览器。
目录
Translations
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$(`
- a
- b
- c
- d
- a
- b
- c
- 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
网友评论