用原生JavaScript實現類jQuery效果

前言:眾所周知,原生JS的DOM API大多都是很難用的,而在十二年前,已經有了一個很實用的庫,它封裝了很多好用的方法,讓JavaScript更有易用性,如今全世界至少70%的網站都在使用,這個庫就是jQuery。為了更容易理解jQuery的實現過程,這篇文章將用原生JS實現jQuery的元素選擇、添加類、獲取/設置文字這幾個方法,當然jQuery的實際實現比這個要復雜的多,本文不做深入研究。


1、實現元素選擇

  • 首先我們需要認識到的是,jQuery實際上就是一個函數,所以最基本的結構應該是這樣的:
windos.jQuery = function(){
  
}

window.$ = window.jQuery // 實現類jQuery寫法 $()
  • 其次我們需要判斷通過該函數傳進來的參數是選擇器還是DOM節點:是選擇器的話,需要使用document.querySelectorAll()來獲取元素,然后返回一個對象用來后續的操作;如果是DOM節點,為了保持操作的一致,也需要將其變為一個對象;如果先用一個變量獲取DOM的集合,再將其以參數傳入,也會返回一個對象(var boxes = document.getElementsByTagName('div') ,再將boxes傳入,進入最后一個分支)。具體代碼如下:
window.jQuery = function(nodeOrSelector){
  let nodes = {}
  // 傳入參數為選擇器
  if (typeof nodeOrSelector === 'string'){
     let temp = document.querySelectorAll(nodeOrSelector)
     for(let i = 0 ; i < temp.length; i++){
        nodes[i] = temp[i]
     }
    nodes['length'] = temp.length
    
  }
  // 傳入參數為節點
  else if(nodeOrSelector instanceof Node){
    nodes={
      0:nodeOrSelector,
      length:1
    }
  }
 // 傳入參數為DOM節點集合
  else{
    for(let i = 0;i<nodeOrSelector.length;i++){
      nodes[i] = nodeOrSelector[i]
    }
    nodes['length'] = nodeOrSelector.length
  }
  
  return nodes
}

2、實現獲取/設置元素的文本

封裝一個Text()函數,操作的是轉化過的nodes對象,如果不傳參,則獲取元素的文本,如果傳參(參數需要是字符串),設置元素的文本為所傳的參數(其中,如果元素是多個節點的集合,那么會為所有的元素都設置文本)。

 nodes.Text = function(text){
    if(text === undefined){
      let texts = []
      for(let i = 0;i<nodes.length;i++){
       texts[i] = nodes[i].textContent
      }
      return texts
    }else{
      for(let i = 0;i<nodes.length;i++){
       nodes[i].textContent = text
      }
    }
  }

3、實現為元素添加/刪除類

封裝一個addClass()函數,操作的轉化過的nodes對象,傳入的參數需要是一個對象,對象的鍵名是需要操作的類,對象的鍵值是操作類型(如{'red':true,'green':false} 表示添加類名為red的類,同時刪除類名為green的類)

  • 首先使用for in循環遍歷傳入的參數,然后使用for循環遍歷nodes節點,對每一個元素都要進行操作,判斷鍵值是true還是false,前者則添加類,后者則刪除類:
nodes.addClass = function(classes){
    for(let key in classes){
      for(let i = 0;i<nodes.length;i++){
        if(classes[key]){
          nodes[i].classList.add(key)
        }else{
          nodes[i].classList.remove(key)
        }
      }  
    }
  }

觀察上面的代碼,發現關于if判斷語句中的兩個分支有相似的地方,而只要有相似的代碼,就有優化的空間,所以進行下面的優化:

nodes.addClass = function(classes){
    for(let key in classes){
      for(let i = 0;i<nodes.length;i++){
        let methodName = classes[key] ? 'add' : 'remove'
        nodes[i].classList[methodName](key)
      }  
    }
  }

4、完整代碼

代碼鏈接

window.jQuery = function(nodeOrSelector) {
  let nodes = {}
  if (typeof nodeOrSelector === 'string') {
    let temp = document.querySelectorAll(nodeOrSelector)
    for (let i = 0; i < temp.length; i++) {
      nodes[i] = temp[i]
    }
    nodes['length'] = temp.length
    console.log(1)

  } else if (nodeOrSelector instanceof Node) {
    nodes = {
      0: nodeOrSelector,
      length: 1
    }
    console.log(2)
  } else {
    for (let i = 0; i < nodeOrSelector.length; i++) {
      nodes[i] = nodeOrSelector[i]
    }
    nodes['length'] = nodeOrSelector.length
    console.log(3)
  }

  nodes.Text = function(text) {
    if (text === undefined) {
      let texts = []
      for (let i = 0; i < nodes.length; i++) {
        texts[i] = nodes[i].textContent
      }
      return texts
    } else {
      for (let i = 0; i < nodes.length; i++) {
        nodes[i].textContent = text
      }
    }
  }
  nodes.addClass = function(classes) {
    for (let key in classes) {
      for (let i = 0; i < nodes.length; i++) {
        let methodName = classes[key] ? 'add' : 'remove'
        nodes[i].classList[methodName](key)
      }
    }
  }


  return nodes
}

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

推薦閱讀更多精彩內容

  • 一、樣式篇 第1章 初識jQuery (1)環境搭建 進入官方網站獲取最新的版本 http://jquery.co...
    凜0_0閱讀 3,443評論 0 44
  • jQuery筆記總結篇 poetries 已關注 2016.10.20 10:52* 字數 9137 閱讀 660...
    小杰的簡書閱讀 1,804評論 2 32
  • 上周末我們鉆石行動“鏡子小組”第五次聚會,主要圍繞大家下半年目標,最重要的那件事是什么? 彪哥是典型的分析型+結構...
    donna王采寧閱讀 279評論 0 0
  • ~致湮滅在時光的友人 一封晚來的回復。
    吃貨者閱讀 217評論 0 0
  • 賢妻良母,良師益友,金玉良言,用心良苦,對你千千萬萬遍,不厭其煩,這個女人真嘮叨,有的時候打著電話,心煩意亂了...
    桐花的童話閱讀 318評論 0 1