模仿jQuery的API实现过程

1. 封装函数

使用原生DOM API以实现【获取所有同类元素并加上同一样式】时,代码如下。


    
选项1
选项2
选项3
选项4
选项5
function getSiblings(node) {
  var allChildren = node.parentNode.children
  var array = {
    length: 0
  }
  for (let i = 0; i < allChildren.length; i++) {
    if (allChildren[i] !== node) {
      array[array.length] = allChildren[i]
      array.length += 1
    }
  }
  return array
}

function addClass(node, classes){
  for(let key in classes){
    var value = classes[key]
    if(value){
      node.classList.add(key)
    }else{
      node.classList.remove(key)
    }
  }
}

此处,为了代码段的复用性,封装为getSiblings()addClass()函数。

2. 使node可以放在前面而不是作为参数传入

方法一:扩展 Node 接口,直接在 Node.prototype 上加函数

缺点:可能会覆盖原有的 Node.prototype 的函数

Node.prototype.getSiblings = function() {
  var allChildren = this.parentNode.children
  var array = {
    length: 0
  }
  for (let i = 0; i < allChildren.length; i++) {
    if (allChildren[i] !== this) {
      array[array.length] = allChildren[i]
      array.length += 1
    }
  }
  return array
}

Node.prototype.addClass = function(classes){
  classes.forEach((value) => this.classList.add(value))
}

方法二:创建命名空间可以很好的避免全局变量名冲突。

window.Node2 = function(node){
  return {
    getSiblings: function(){
      var allChildren = node.parentNode.children
      var array = {
        length: 0
      }
      for(let i=0;i node.classList.add(value))
    }
  }
}

var node2 = Node2(item3)
node2.getSiblings()
node2.addClass()

3. 将该命名改为jQuery

window.jQuery = function(nodeOrSelector) {
  let node
  if (typeof nodeOrSelector === 'string') {
    node = document.querySelector(nodeOrSelector)
  } else {
    node = nodeOrSelector
  }
  return {
    getSiblings: function() {
      var allChildren = node.parentNode.children
      var array = {
        length: 0
      }
      for (let i = 0; i < allChildren.length; i++) {
        if (allChildren[i] !== node) {
          array[array.length] = allChildren[i]
          array.length += 1
        }
      }
      return array
    },
    addClass: function(classes) {
      classes.forEach((value) => node.classList.add(value))
    }
  }
}

var node2 = jQuery('div:nth-child(3)')
node2.getSiblings()
node2.addClass(['red', 'b', 'c'])

4. 完成一个模仿jQuery的API

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
      }
    }

    nodes.addClass = function(classes) {
      classes.forEach((value) => {
        for (let i = 0; i < nodes.length; i++) {
          nodes[i].classList.add(value)
        }
      })
    }
    nodes.text = function(text) {
      if (text === undefined) {
        var texts = []
        for (let i = 0; i < nodes.length; i++) {
          texts.push(nodes[i].textContent)
        }
        return texts
      } else {
        for (let i = 0; i < nodes.length; i++) {
          nodes[i].textContent = text
        }
      }
    }
      return nodes
    }

    var node2 = jQuery('div')
    node2.addClass(['red', 'b', 'c'])
    node2.text('hi')

此时已经可以使用jQuery(selector)与方法addClass()text()来便利地满足一些需求了,但是由于这里jQuery写起来太费劲,再为它设置一个缩写$

window.$ = function(nodeOrSelector) {
  let nodes = {}
  ……
  nodes.addClass = function(){ }
  return nodes
}

此后只需$(selector)就可以轻松愉悦地定位元素以及使用封装好的函数了

5. 总结

实现简易的jQuery的API后容易发现,jQuery就是一个封装好的函数库,将原生JS的各种API重新写成了高效率,高语义化,高兼容性的API,给开发带来了非常大的便利。

你可能感兴趣的:(模仿jQuery的API实现过程)