前端发展很快,现代浏览器原生 API 已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用场景大大减少。本项目总结了大部分 jQuery API 替代的方法,暂时只支持 IE10+ 以上浏览器。
常用的 class、id、属性 选择器都可以使用 document.querySelector
或 document.querySelectorAll
替代。区别是
document.querySelector
返回第一个匹配的 Elementdocument.querySelectorAll
返回所有匹配的 Element 组成的 NodeList。它可以通过[].slice.call()
把它转成 Array- 如果匹配不到任何元素,jQuery 返回空数组 []
,但
document.querySelector返回返回
null`,注意空指针异常
// query by class
$('.css')
document.querySelectorAll('.css')
// query by id
$('#id')
el.querySelectorAll('#id')
// query by attribute
$('a[target=_blank]')
document.querySelectorAll('a[target=_blank]')
// find
$el.find('li')
el.querySelectorAll('li')
// body
$('body')
document.body
// attr
$el.attr('foo')
e.getAttribute('foo')
// data attribute
$el.data('foo')
// using getAttribute
el.getAttribute('data-foo');
// IE 11+ 开始支持 `dataset`
el.dataset['foo']
// siblings
$el.siblings();
[].filter.call(el.parentNode.children, function(child) {
return child !== el;
})
// prev
$el.prev();
el.previousElementSibling
// next
$el.next();
el.nextElementSibling
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;
}
Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.
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;
}
jQuery 对象的 iframe contents()
返回的是 iframe 内的 document
// contents
$iframe.contents()
iframe.contentDocument
// query
$iframe.contents().find('.css')
iframe.contentDocument.querySelectorAll('.css')
// set css
$el.css('border-width', 20)
el.style.borderWidth = '20px'
// addClass
$el.addClass(className)
el.classList.add(className);
// removeClass
$el.removeClass(className)
el.classList.remove(className);
// hasClass
$el.hasClass(className)
el.classList.contains(className);
// toggleClass
$el.toggleClass(className)
el.classList.toggle(className);
// get style
$el.css("color");
// 注意:此处为了解决当 style 值为 auto 时,返回 auto 的问题
const win = el.ownerDocument.defaultView;
// null 的意思是不返回伪类元素
win.getComputedStyle(el, null).color;
// set style
$el.css({ color: "#ff0011" });
el.style.color = '#ff0011';
注意,如果想一次设置多个 style,可以参考 oui-dom-utils 中 setStyles 方法
Width 与 Height 获取方法相同,下面以 Height 为例:
// window height
$(window).height();
// 不含 scrollbar,与 jQuery 行为一致
window.document.documentElement.clientHeight
// 含 scrollbar
window.innerHeight
// document height
$(document).height();
document.documentElement.scrollHeight
// el height
$el.height();
// 与 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 .contents() 方法返回 iframe 的 contentDocument
$('iframe').contents().height()
iframe.contentDocument.documentElement.scrollHeight
// position
$el.position();
{ left: el.offsetLeft, top: el.offsetTop }
// offset
$el.offset();
function getOffset (el) {
let box = el.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - document.documentElement.clientTop,
left: box.left + window.pageXOffset - document.documentElement.clientLeft
}
}
// remove
$el.remove()
el.parentNode.removeChild(el);
// get text
$el.text()
el.textContent
// set text
$el.text(string)
el.textContent = string
// get html
$el.html()
el.innerHTML
// set html
$el.html(htmlString)
el.innerHTML = htmlString
append 插入到子节点的末尾
jQuery
$el.append("<div id='container'>hello</div>")
Native
let newEl = document.createElement('div');
newEl.setAttribute('id', 'container');
newEl.innerHTML = 'hello';
el.appendChild(newEl)
jQuery
$el.prepend("<div id='container'>hello</div>")
Native
let newEl = document.createElement('div')
newEl.setAttribute('id', 'container')
newEl.innerHTML = 'hello'
el.insertBefore(newEl, el.firstChild)
Insert a new node before the selected elements
jQuery
$newEl.insertBefore(queryString);
Native
newEl.insertBefore(document.querySelector(queryString))
Insert a new node after the selected elements
jQuery
$newEl.insertAfter(queryString);
Native
function insertAfter(newEl, queryString) {
var parent = document.querySelector(queryString).parentNode;
if (parent.lastChild === newEl) {
parent.appendChild(newEl);
} else {
parent.insertBefore(newEl, parent.nextSibling);
}
},
// scrollTop
$(window).scrollTop()
(document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
Replace with fetch and fetch-jsonp
For a complete replacement with namespace and delegation, refer to https://github.com/oneuijs/oui-dom-events
// bind an event with on
$el.on(eventName, eventHandler);
el.addEventListener(eventName, eventHandler);
// unbind an event with off
$el.off(eventName, eventHandler);
el.removeEventListener(eventName, eventHandler);
jQuery
$(el).trigger('custom-event', {key1: 'data'});
Native
if (window.CustomEvent) {
var event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
} else {
var event = document.createEvent('CustomEvent');
event.initCustomEvent('custom-event', true, true, {key1: 'data'});
}
el.dispatchEvent(event);
$('#my-input').val()
document.querySelector('#my-input').value
// 获取 e.currentTarget 相对于 .radio 选择结果的索引
$(e.currentTarget).index('.radio')
[].indexOf.call(document.querySelectAll('.radio'), e.currentTarget)
// isArray IE10+
$.isArray(range)
Array.isArray(range)
// trim
$.trim(string)
String.trim(string)
// extend, use object.assign polyfill https://github.com/ljharb/object.assign
$.extend({}, defaultOpts, opts)
Object.assign({}, defaultOpts, opts)
// contains
$.contains(el, child);
el !== child && el.contains(child);
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
MIT