jQuery is out of date

在我看來,jQuery確實已通過時了。本項目總結了絕大部分 jQuery API 替代的方法,相似項目You-Dont-Need-jQuery,並會再此基礎上進行不少的補充。寫這個項目主要想讓本身和你們增進對javascript原生api的理解,也能夠做爲一個"原生jquery"的api文檔隨時查看。兼容ie9及以上瀏覽器,如不支持ie9會特別說明。javascript

原文地址 https://github.com/fa-ge/jQuery-is-out-of-datecss

目錄

  1. Regulationhtml

  2. DOM Manipulationjava

  3. Query Selectornode

  4. Ajaxjquery

  5. Eventsgit

  6. Utilitiesgithub

  7. Animationweb

Regulation

function $(selector) {
  return document.querySelector(selector)
}

function $$(selector) {
  return Array.prototype.slice.call(document.querySelectorAll(selector))
}

若是在jQuery示例下的$是jquery對象,在Native示例下的$是以上的實現。至關於實現了chrome控制檯上$,$$方法。chrome

DOM Manipulation

不少人一直認爲jQuery尚未過期的其中一個緣由是在DOM操做上很是方便。接下來比較一下。

add

添加元素到匹配的元素集合。

// jQuery
$(selector).add($(newEl))

// Native
$$(selector).push(newEl)

addClass

爲每一個匹配的元素添加指定的樣式類名

// jQuery
$(el).addClass(className)

// Native (IE 10+ support)
el.classList.add(className)

after

在匹配元素集合中的每一個元素後面插入參數所指定的內容,做爲其兄弟節點。

// jQuery
$(el).after('<p></p>')

// Native (Html string)
el.insertAdjacentHTML('afterend', '<p></p>')

// Native (Element)
el.insertAdjacentElement('afterend', newEl)

// Native (Element)
el.parentNode.insertBefore(newEl, el.nextSibling)

append

在每一個匹配元素裏面的末尾處插入參數內容。

// jQuery
$(el).append('<p></p>')

// Native (Html string)
el.insertAdjacentHTML('beforeend', '<p></p>')

// Native (Element)
el.insertAdjacentElement('beforeend', newEl)

// Native (Element)
el.appendChild(newEl)

appendTo

append相反

attr

獲取匹配的元素集合中的第一個元素的屬性的值。設置每個匹配元素的一個或多個屬性。

// jQuery
$(el).attr('foo')

// Native
el.getAttribute('foo')

// jQuery
$(el).attr('foo', 'bar')

// Native
el.setAttribute('foo', 'bar')

before

根據參數設定,在匹配元素的前面插入內容(外部插入)

// jQuery
$(el).before('<p></p>')

// Native (Html string)
el.insertAdjacentHTML('beforebegin', '<p></p>')

// Native (Element)
el.insertAdjacentElement('beforebegin', newEl)

// Native (Element)
el.parentNode.insertBefore(newEl, el)

children

得到匹配元素集合中每一個元素的子元素,選擇器選擇性篩選。

// jQuery
$(el).children()

// Native
el.children

clone

建立一個匹配的元素集合的深度拷貝副本。

// jQuery
$(el).clone()

// Native
el.cloneNode()

// For Deep clone , set param as `true`

closest

從元素自己開始,在DOM 樹上逐級向上級元素匹配,並返回最早匹配的祖先元素。以數組的形式返回與選擇器相匹配的全部元素,從當前元素開始,在 DOM 樹中向上遍歷。

// jQuery
$el.closest(selector)

// Native - Only latest, NO IE
el.closest(selector)

// Native
function closest(el, selector = false) {
  const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
  do {
    if (matchesSelector.call(el, selector)) {
      return el
    }
  } while ((el = el.parentElement) !== null)
  return null
}

contents

得到匹配元素集合中每一個元素的子元素,包括文字和註釋節點。

// jQuery
$(el).contents()

// Native
el.childNodes

css

獲取匹配元素集合中的第一個元素的樣式屬性的值設置每一個匹配元素的一個或多個CSS屬性。

// jQuery
$(el).css('color')

// Native
// 注意:此處爲了解決當 style 值爲 auto 時,返回 auto 的問題
const win = el.ownerDocument.defaultView

// null 的意思是不返回僞類元素
win.getComputedStyle(el, null).color

// jQuery
$(el).css({ color: '#f01' })

// Native
el.style.color = '#f01'

// 一次性設置多個樣式
// jQuery
$(el).css({ color: '#f01', 'background-color': '#000' })

// Native
const cssObj = {color: '#f01', backgroundColor: '#000'}
for (let key in cssObj) {
  el.style[key] = cssObj[key]
}

// Native
const cssText = 'color: #f01; background-color: #000'
el.style.cssText += cssText

empty

從DOM中移除集合中匹配元素的全部子節點。

// jQuery
$(el).empty()

// Native
el.innerHTML = ''

filter

篩選元素集合中匹配表達式 或 經過傳遞函數測試的 那些元素集合。

// jQuery
$(selector).filter(filterFn)

// Native
$$(selector).filter(filterFn)

find

經過一個選擇器,jQuery對象,或元素過濾,獲得當前匹配的元素集合中每一個元素的後代。

// jQuery
$(el).find(selector)

// Native
el.querySelectorAll(selector)

has

篩選匹配元素集合中的那些有相匹配的選擇器或DOM元素的後代元素。

// jQuery
$(selector).has('p')

// Native
$$(selector).filter(el => el.querySelector('p') !== null)

hasClass

肯定任何一個匹配元素是否有被分配給定的(樣式)類。

// jQuery
$(el).hasClass(className)

// Native (IE 10+ support)
el.classList.contains(className)

height

獲取匹配元素集合中的第一個元素的當前計算高度值。設置每個匹配元素的高度值。

// jQuery window
$(window).height()

// Native
window.innerHeight

// jQuery document
$(document).height()

// Native
const body = document.body
const html = document.documentElement
const height = Math.max(
  body.offsetHeight,
  body.scrollHeight,
  html.clientHeight,
  html.offsetHeight,
  html.scrollHeight
)

// jQuery Element (it's `height` always equals to content height)
$(el).height()

// Native
function getHeight(el) {
  const styles = window.getComputedStyle(el)
  const height = el.clientHeight
  const paddingTop = parseFloat(styles.paddingTop)
  const paddingBottom = parseFloat(styles.paddingBottom)
  return height - paddingTop - paddingBottom
}

// Native
// when `border-box`, it's `height` === (content height) + padding + border; when `content-box`, it's `height` === (content height)
getComputedStyle(el, null).height

html

獲取集合中第一個匹配元素的HTML內容 設置每個匹配元素的html內容。

// jQuery
$(el).html()

// Native
el.innerHTML

// jQuery
$(el).html(htmlString)

// Native
el.innerHTML = htmlString

innerHeight

爲匹配的元素集合中獲取第一個元素的當前計算高度值,包括padding,可是不包括border。

// jQuery
$(el).innerHeight()

// Native
el.clientHeight()

innerWidth

爲匹配的元素集合中獲取第一個元素的當前計算寬度值,包括padding,可是不包括border。

// jQuery
$(el).innerWidth()

// Native
el.clientWidth()

insertAfter

after相反

insertBefore

before相反

is

判斷當前匹配的元素集合中的元素,是否爲一個選擇器,DOM元素,或者jQuery對象,若是這些元素至少一個匹配給定的參數,那麼返回true。

// jQuery
$(el).is(selector)

// Native
(el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector)

next

取得匹配的元素集合中每個元素緊鄰的後面同輩元素的元素集合。若是提供一個選擇器,那麼只有緊跟着的兄弟元素知足選擇器時,纔會返回此元素。

// jQuery
$(el).next()

// Native
el.nextElementSibling

nextAll

得到每一個匹配元素集合中全部下面的同輩元素,選擇性篩選的選擇器。

// jQuery
$(el).nextAll()

// Native
const nextAll = []
while((el = el.nextElementSibling) !== null) {
  nextAll.push(el)
}

not

從匹配的元素集合中移除指定的元素。

// jQuery
$(selector).not(matches)

// Native
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
$$(selector).filter(el => !matchesSelector.call(el, matches))

offset

在匹配的元素集合中,獲取的第一個元素的當前座標,座標相對於文檔。 設置匹配的元素集合中每個元素的座標, 座標相對於文檔。

// jQuery
$(el).offset()

// Native
const elClientRect = el.getBoundingClientRect()
{
  top: elClientRect.top + window.pageYOffset - document.documentElement.clientTop,
  left: elClientRect.left + window.pageXOffset - document.documentElement.clientLeft
}

// jQuery
$(el).offset(10, 10)

// Native
const elClientRect = el.getBoundingClientRect()
const elTop = 10 - elClientRect.top - document.documentElement.clientTop
const elLeft = 10 - elClientRect.left - document.documentElement.clientLeft
el.style.cssText += `position: relative;top: ${elTop}px;left: ${elLeft}px;`

offsetParent

// jQuery
$(el).offsetParent()

// Native
el.offsetParent || el

outerHeight

獲取元素集合中第一個元素的當前計算高度值,包括padding,border和選擇性的margin。返回一個整數(不包含「px」)表示的值  ,或若是在一個空集合上調用該方法,則會返回 null。

// jQuery
$(el).outerHeight()

// Native
el.offsetHeight

// jQuery
$(el).outerHeight(true)

// Native
const win = el.ownerDocument.defaultView
const {marginTop, margintBottom} = win.getComputedStyle(el, null)
el.offsetHeight + parseFloat(marginTop) + parseFloat(margintBottom) === $(el).outerHeight(true) // true

outerWidth

outerHeight相似。

parent

取得匹配元素集合中,每一個元素的父元素,能夠提供一個可選的選擇器。

// jQuery
$(el).parent()

// Native
el.parentNode

parents

得到集合中每一個匹配元素的祖先元素,能夠提供一個可選的選擇器做爲參數。

// jQuery
$(el).parents(selector)

// Native
function parents(el, selector = '*') {
  const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
  const parentsMatch = []
  while ((el = el.parentElement) !== null) {
    if (matchesSelector.call(el, selector)) {
      parentsMatch.push(el)
    }
  }
  return parentsMatch
}

parentsUntil

查找當前元素的全部的前輩元素,直到遇到選擇器, DOM 節點或 jQuery 對象匹配的元素爲止,但不包括這些元素。

// jQuery
$(el).parentsUntil(selector)

// Native
function parentsUntil(el, selector = false) {
  const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
  const parentsMatch = []
  while ((el = el.parentElement) !== null && !matchesSelector.call(el, selector)) {
      parentsMatch.push(el)
  }
  return parentsMatch
}

position

獲取匹配元素中第一個元素的當前座標,相對於offset parent的座標。( offset parent指離該元素最近的並且被定位過的祖先元素 )

// jQuery
$(el).position()

// Native
{ left: el.offsetLeft, top: el.offsetTop }

prepend

將參數內容插入到每一個匹配元素的前面(元素內部)。

// jQuery
$(el).prepend('<p></p>')

// Native (HTML string)
el.insertAdjacentHTML('afterbegin', '<p></p>')

// Native (Element)
el.insertBefore(newEl, el.firstChild)

prependTo

prepend相反

prev

取得一個包含匹配的元素集合中每個元素緊鄰的前一個同輩元素的元素集合。選擇性篩選的選擇器。

next相似

prevAll

得到集合中每一個匹配元素的全部前面的兄弟元素,選擇性篩選的選擇器。

nextAll相似

prevUntil

獲取每一個元素但不包括選擇器,DOM節點,或者jQuery對象匹配的元素的全部前面的兄弟元素。

nextUntil相似

remove

將匹配元素集合從DOM中刪除。(注:同時移除元素上的事件及 jQuery 數據。)

// jQuery
$(el).remove()

// Native
el.parentNode.removeChild(el)

// Native
el.outerHTML = ''

removeAttr

爲匹配的元素集合中的每一個元素中移除一個屬性(attribute)。

// jQuery
$(el).removeAttr(attr)

// Native
el.removeAttribute(attr)

removeClass

移除集合中每一個匹配元素上一個,多個或所有樣式。

// jQuery
$(el).removeClass(className)

// Native (IE 10+ support)
el.classList.remove(className)

replaceAll

replaceWith相反

replaceWith

用提供的內容替換集合中全部匹配的元素而且返回被刪除元素的集合。

// jQuery
$(el).replaceWith('<p></p>')

// Native (HTML string)
el.outerHTML = '<p></p>'

// Native (Element)
el.parentNode.replaceChild(newEl, el)

scrollLeft

scrollTop同樣

scrollTop

獲取匹配的元素集合中第一個元素的當前垂直滾動條的位置或設置每一個匹配元素的垂直滾動條位置。設置每一個匹配元素的垂直滾動條位置

// jQuery
$(el).scrollTop()

// Native (el is window)
Math.max(document.documentElement.scrollTop, document.body.scrollTop)
or
window.pageYOffset

// Native (el is not window)
el.scrollTop

// jQuery
$(el).scrollTop(10)

// Native (el is window)
document.documentElement.scrollTop = 10
document.body.scrollTop = 10

// Native (el is not window)
el.scrollTop = 10

siblings

得到匹配元素集合中每一個元素的兄弟元素,能夠提供一個可選的選擇器。。

// jQuery
$(el).siblings()

// Native

slice

根據指定的下標範圍,過濾匹配的元素集合,並生成一個新的 jQuery 對象。

// jQuery
$(selector).slice(1, 6)

// Native
$$(selector).slice(1, 6)

text

獲得匹配元素集合中每一個元素的合併文本,包括他們的後代設置匹配元素集合中每一個元素的文本內容爲指定的文本內容。

// jQuery
$(el).text()

// Native
el.textContent

// jQuery
$(el).text(string)

// Native
el.textContent = string

toggleClass

在匹配的元素集合中的每一個元素上添加或刪除一個或多個樣式類,取決於這個樣式類是否存在或值切換屬性。即:若是存在(不存在)就刪除(添加)一個類。

// jQuery
$(el).toggleClass(className)

// Native
el.classList.toggle(className)

unwrap

將匹配元素集合的父級元素刪除,保留自身(和兄弟元素,若是存在)在原來的位置。

// jQuery
$(el).unwrap()

// Native
const parent = el.parentNode
parent.outerHTML = parent.innerHTML

val

獲取匹配的元素集合中第一個元素的當前值。設置匹配的元素集合中每一個元素的值。

// jQuery
$(el).val()

// Native
el.value

// jQuery
$(el).val(value)

// Native
el.value = value

width

height相似

wrap

在每一個匹配的元素外層包上一個html元素。

// jQuery
$(el).wrap('<div class="wrapper"></div>')

// Native
const wrapper = document.createElement('div')
wrapper.className = 'wrapper'
el.parentNode.insertBefore(wrapper, el)
el.parentNode.removeChild(el)
wrapper.appendChild(el)

// Native
// 這種性能比較差 https://jsperf.com/outerhtml-appendchild
el.outerHTML = `<div class="wrapper">${el.outerHTML}</div>`

Query Selector

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

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

  • document.querySelectorAll 返回全部匹配的 Element 組成的 NodeList。它能夠經過 [].slice.call() 把它轉成 Array

  • 若是匹配不到任何 Element,jQuery 返回空數組 [],但 document.querySelector 返回 null,注意空指針異常。

注意:document.querySelector 和 document.querySelectorAll 性能很。若是想提升性能,儘可能使用 document.getElementByIddocument.getElementsByClassName 或 document.getElementsByTagName

如下只實現和jquery有所區別的api

:contains

選擇全部包含指定文本的元素。

// jQuery
$('selector:contains("metchString")')

// Native
$$('selector').filter(el => el.textContent.indexOf('metchString') !== -1)

:emtpy

選擇全部沒有子元素的元素(包括文本節點)。

// jQuery
$('selector:empty')

// Native
$$('selector').filter(el => el.innerHTML === '')

:even

選擇索引值爲偶數的元素,從 0 開始計數。

// jQuery
$('selector:even')

// Native
$$('selector').filter((el, index) => (index & 1) === 0)

:focus

選擇當前獲取焦點的元素。

// jQuery
$(':focus')

// Native
document.activeElement

:gt

選擇匹配集合中全部大於給定index(索引值)的元素。

// jQuery
$('selector:gt(2)')

// Native
$$('selector').filter((el, index) => index > 2)

:has

has相似

:header

選擇全部標題元素,像h1, h2, h3 等.

// jQuery
$('selector:header')

// Native
$$('selector').filter(el => /^h\d$/i.test(el.nodeName))

:lt

選擇匹配集合中全部索引值小於給定index參數的元素。

// jQuery
$('selector:lt(2)')

// Native
$$('selector').filter((el, index) => index < 2)

:not

not相似

:odd

選擇索引值爲奇數元素,從 0 開始計數。

// jQuery
$('selector:odd')

// Native
$$('selector').filter((el, index) => (index & 1) === 1)

only-child

若是某個元素是其父元素的惟一子元素,那麼它就會被選中。

// jQuery
$('selector:only-child')

// Native
$$('selector').filter(el => el.previousElementSibling === null && el.nextElementSibling === null)

// Native
$$('selector').filter(el => el.parentNode.children.length === 1)

:only-of-type

選擇器匹配屬於其父元素的特定類型的惟一子元素的每一個元素。

// jQuery
$('selector:only-of-type')

// Native
$$('selector').filter(el => {
  for(let child of el.parentNode.children) {
    if (child !== el && child.nodeName === el.nodeName) {
      return true
    }
  }
  return false
})

:parent

選擇全部含有子元素或者文本的父級元素。

// jQuery
$('selector:parent')

// Native
$$('selector').filter(el => el.innerHTML !== '')

:selected

獲取 select 元素中全部被選中的元素。

// jQuery
$('select option:selected')

// Native (single)
$('select option')[$('select').selectedIndex]

// Native (multiple)
$$('select option').filter(el => el.selected)

Ajax

Events

Utilities

contains

檢查一個DOM元素是另外一個DOM元素的後代。

// jQuery
$.contains(el, child)

// Native
el !== child && el.contains(child)

each

一個通用的迭代函數,它能夠用來無縫迭代對象和數組。數組和相似數組的對象經過一個長度屬性(如一個函數的參數對象)來迭代數字索引,從0到length - 1。其餘對象經過其屬性名進行迭代。

// jQuery
$.each(array, (index, value) => {})

// Native
array.forEach((value, index) => {})

extend

將兩個或更多對象的內容合併到第一個對象。

// jQuery
$.extend({}, {a: 1}, {b: 2}) // {a: 1, b: 2}

// ES6-way
Object.assign({}, {a: 1}, {b: 2}) // {a: 1, b: 2}

globalEval

在全局上下文下執行一些JavaScript代碼。

// jQuery
$.globaleval(code)

// Native
function Globaleval(code) {
  const script = 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)

grep

查找知足過濾函數的數組元素。原始數組不受影響。

// jQuery
$.grep([10,11,3,4], n => n > 9)

// Native
[10,11,3,4].filter(n => n > 9)

inArray

在數組中查找指定值並返回它的索引(若是沒有找到,則返回-1)。

// jQuery
$.inArray(item, array)

// Native
array.indexOf(item) > -1

// ES6-way
array.includes(item)

isArray

肯定的參數是一個數組。

// jQuery
$.isArray(array)

// Native
Array.isArray(array)

isEmptyObject

檢查對象是否爲空(不包含任何屬性)。

// jQuery
$.isEmptyObject(obj)

// Native
function isEmptyObject(obj) {
  return Object.keys(obj).length === 0
}

isFunction

肯定參數是否爲一個Javascript 函數。

// jQuery
$.isFunction(item)

// Native
function isFunction(item) {
  if (typeof item === 'function') {
    return true
  }
  var type = Object.prototype.toString(item)
  return type === '[object Function]' || type === '[object GeneratorFunction]'
}

isNumeric

肯定它的參數是不是一個數字。

// jQuery
$.isNumeric(item)

// Native
function isNumeric(value) {
  var type = typeof value

  return (type === 'number' || type === 'string') && !isNaN(value - parseFloat(value))
}

isPlainObject

測試對象是不是純粹的對象(經過 "{}" 或者 "new Object" 建立的)

// jQuery
$.isPlainObject(obj)

// Native
function isPlainObject(obj) {
  if (typeof (obj) !== 'object' || obj.nodeType || obj !== null && obj !== undefined && obj === obj.window) {
    return false
  }

  if (obj.constructor &&
      !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {
    return false
  }

  return true
}

isWindow

肯定參數是否爲一個window對象。

// jQuery
$.isWindow(obj)

// Native
function isWindow(obj) {
  return obj !== null && obj !== undefined && obj === obj.window
}
// jquery源碼中是這麼判斷對象是否爲window的,個人理解是代碼可能會跑到服務器上,由於服務器上是沒有window對象的。因此這麼判斷

makeArray

轉換一個相似數組的對象成爲真正的JavaScript數組。

// jQuery
$.makeArray(arrayLike)

// Native
Array.prototype.slice.call(arrayLike)

// ES6-way
Array.from(arrayLike)

map

將一個數組中的全部元素轉換到另外一個數組中。

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

// Native
array.map((value, index) => {
})

merge

合併兩個數組內容到第一個數組。

// jQuery
$.merge(array1, array2)

// Native
// But concat function doesn't remove duplicate items.
function merge(...args) {
  return [].concat(...args)
}

now

返回一個數字,表示當前時間。

// jQuery
$.now()

// Native
Date.now()

// Native
+new Date()

// Native
new Date().getTime()

parseHTML

將字符串解析到一個DOM節點的數組中。

// jQuery
$.parseHTML(string)

// Native
function parseHTML(string) {
  const context = document.implementation.createHTMLDocument()

  // Set the base href for the created document so any parsed elements with URLs
  // are based on the document's URL
  const base = context.createElement('base')
  base.href = document.location.href
  context.head.appendChild(base)

  context.body.innerHTML = string
  return context.body.childNodes
}

// Native (IE 10+ support)
// 二者性能差很少 https://jsperf.com/parsehtml2
function parseHTML(string) {
  const context = new DOMParser().parseFromString(string, "text/html")
  return context.body.childNodes
}

parseJSON

接受一個標準格式的 JSON 字符串,並返回解析後的 JavaScript 對象。

// jQuery
$.parseJSON(str)

// Native
JSON.parse(str)

parseXML

解析一個字符串到一個XML文檔。

// jQuery
jQuery.parseXML(xmlString)

// Native
new DOMParser().parseFromString(xmlString, 'application/xml')

proxy

接受一個函數,而後返回一個新函數,而且這個新函數始終保持了特定的上下文語境。

// jQuery
$.proxy(fn, context)

// Native
fn.bind(context)

trim

去掉字符串起始和結尾的空格。

// jQuery
$.trim(string)

// Native
string.trim()

type

肯定JavaScript 對象的類型[[Class]] 。

// jQuery
$.type(obj)

// Native
function type(item) {
  const reTypeOf = /(?:^\[object\s(.*?)\]$)/
  return Object.prototype.toString.call(item)
    .replace(reTypeOf, '$1')
    .toLowerCase()
}

Animation

有哪塊錯誤的或者不懂得能夠在github上提個issue。若是哪塊有更好的解法能夠pr。

相關文章
相關標籤/搜索