仿寫 jQuery

在 jQuery 中,要為特定元素添加 class 很方便,只需要使用調(diào)用addClass方法即可,例如為所有 div 添加 一個(gè)叫 red 的 class 只需要寫 $("div").addClass("red")。這與使用瀏覽器 api 實(shí)現(xiàn)同樣的功能相比要簡(jiǎn)潔明了不少。本文通過逐漸改進(jìn)的方式,實(shí)現(xiàn)一個(gè)從調(diào)用角度上與其類似的 api。

首先,先使用最直接的方式實(shí)現(xiàn)功能,傳入一組節(jié)點(diǎn)和一個(gè)類名,為這組節(jié)點(diǎn)添加這個(gè)類

addClass = function (nodes, className) {
  nodes.forEach(function (el) {
    el.classList.add(className)
  })
}

let nodes = document.querySelectorAll('div')
addClass.call(undefined, nodes, 'red')

這個(gè)方式有個(gè)缺點(diǎn)是只能一次添加一個(gè)類,如果需要添加多個(gè)則需要調(diào)用多次,不太方便。因?yàn)槲覀兛梢越柚瘮?shù)中的arguments獲取到傳入的所有(非this)參數(shù),所以 className 這個(gè)參數(shù)也可以舍去,下面是可以一次性添加多個(gè)類的實(shí)現(xiàn)。

addClass = function (nodes) {
  let args = arguments
  nodes.forEach(function (el) {
    for (let i = 1; i < args.length; i++) {
      el.classList.add(args[i])
    }
  })
}

let nodes = document.querySelectorAll('div')
addClass.call(undefined, nodes, 'red', 'foo')

對(duì)比 jQuery 中的實(shí)現(xiàn)可以發(fā)現(xiàn),這里每次都要先獲取到節(jié)點(diǎn)然后再操作,而使用 jQuery 則一般直接傳入選擇器。所以這里可以進(jìn)一步改造,使其適應(yīng)選擇器和節(jié)點(diǎn)參數(shù)。

addClass = function (nodeOrSelector) {
  let args = arguments
  if (typeof nodeOrSelector === 'string') {
    nodes = document.querySelectorAll(nodeOrSelector)
  } else {
    nodes = nodeOrSelector
  }
  nodes.forEach(function (el) {
    for (let i = 1; i < args.length; i++) {
      el.classList.add(args[i])
    }
  })
}

addClass.call(undefined, 'div', 'red', 'foo')

到這里,實(shí)際上與 jQuery 的 api 已經(jīng)有幾分相似之處了,但是這里有一個(gè)明顯的問題,那就是如果用戶自己也定義了一個(gè) addClass,那么我們的 addClass 就會(huì)被覆蓋掉。因此,我們應(yīng)該創(chuàng)建一個(gè)“獨(dú)立的區(qū)域”用來存放這個(gè)函數(shù)。

window.$ = {
  addClass: function (nodeOrSelector) {
    let args = arguments
    if (typeof nodeOrSelector === 'string') {
      nodes = document.querySelectorAll(nodeOrSelector)
    } else {
      nodes = nodeOrSelector
    }
    nodes.forEach(function (el) {
      for (let i = 1; i < args.length; i++) {
        el.classList.add(args[i])
      }
    })
  }
}

$.addClass.call(undefined, 'div', 'red', 'foo')

改完以后和 jQuery 更像了,就差最后幾步了。實(shí)際上,如果我們執(zhí)行typeof $(在引入了 jQuery的前提下),可以發(fā)現(xiàn)它實(shí)際上是個(gè)函數(shù)。也就是說其實(shí)應(yīng)該模仿它,將上面的代碼也封裝成一個(gè)函數(shù)。完成后的完整代碼如下:

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .red {color: red; background-color: black;}
    </style>
</head>
<body>
<div>DIV1</div>
<div>DIV2</div>
<div>DIV3</div>
<script src="./main.js"></script>
</body>
</html>

// main.js
window.jQuery = function (nodeOrSelector) {
  let nodes

  if (typeof nodeOrSelector === 'string') {
    nodes = document.querySelectorAll(nodeOrSelector)
  } else {
    nodes = {
      0: nodeOrSelector,
      length: 1,
    }
  }

  nodes.addClass = function () {
    let classArray = arguments
    nodes.forEach(function (el) {
      for (let className of classArray ){
        el.classList.add(className)
      }
    })
  }

  return nodes
}

window.$ = window.jQuery

setTimeout(function () {
  let $div = $('div')
  $div.addClass('red', 'foo', 'bar')
}, 1000)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容