自己实现一个jQuery的API

150 阅读3分钟

我们先思考一个问题:用DOM API 获取一个元素的兄弟姐妹元素应该怎么做?

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>自己实现一个jQuery的API</title>
</head>

<body>
  <ul>
    <li id="item1">选项1</li>
    <li id="item2">选项2</li>
    <li id="item3">选项3</li>
    <li id="item4">选项4</li>
    <li id="item5">选项5</li>
  </ul>
  
  <script>
    var allChildren = item3.parentNode.children
    var array = {
      length: 0
    }
    for (let i = 0; i < allChildren.length; i++) {
      if (allChildren[i] !== item3) {
        array[array.length] = allChildren[i]
        array.length += 1
      }
    }
    console.log(array)
  </script>
</body>

</html>

效果如图1:

接下来封装一下,所谓封装就是起个名字,写个函数:

function getSiblings(node) { /*这就是一个API*/
  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
}
console.log(getSiblings(item3))

运行效果如图2:

好啦自己写的一个API已经可以正常使用了!

然后再写一个添加class的AP

封装一个函数:function addClass(node, classes){}

如果我们要给item3添加三个class,分别是a,b,c应该怎么做呢:

item3.classList.add('a')
item3.classList.add('b')
item3.classList.add('c')

效果如图3:

这代码也太丑了!有没有简洁的方法呢:

var classes = ['a','b','c']
classes.forEach((value)=> item3.classList.add(value))

能不能做到既能add又能remove呢?用哈希来做:

var classes = {'a':true,'b':false,'c':true}

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

效果如图4:

接下来封装一下:

function addClass(node,classes){
   /* var classes = {'a':true,'b':false,'c':true} */

  for(let key in classes){
    var value = classes[key]
    if(value){
      node.classList.add(key)
    }else{
      node.classList.remove(key)
    }
  }
}
addClass(item3,{'a': true, 'b': false, 'c': true})

效果如图5:

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>自己实现一个jQuery的API</title>
</head>

<body>
  <ul>
    <li id="item1">选项1</li>
    <li id="item2">选项2</li>
    <li id="item3">选项3</li>
    <li id="item4">选项4</li>
    <li id="item5">选项5</li>
  </ul>
  <script>
   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
  }
  console.log( getSiblings(item3) )
  
  function addClass(node,classes){
     /* var classes = {'a':true,'b':false,'c':true} */
  
    for(let key in classes){
      var value = classes[key]
      if(value){
        node.classList.add(key)
      }else{
        node.classList.remove(key)
      }
    }
  }
  
  addClass(item3,{'a': true, 'b': false, 'c': true})
  
  </script>
</body>
</html>

接下来把代码优化一下:

function addClass(node,classes){
   /* var classes = {'a':true,'b':false,'c':true} */

  for(let key in classes){
    var value = classes[key]
    var methodName = value ? 'add' : 'remove'
    node.classList.add[methodName](key)
  }
}

这两个API就写好了。 二、起个名字吧(命名空间)就叫jamDom

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){
  classes.forEach( (value)=> node.classList.add(value) )
}

window.jamDom = {}
jamDom.getSiblings = getSiblings
jamDom.addClass = addClass

jamDom.getSiblings(item3)
jamDOm.addClass(item3 , ['a','b','c'])

再优化一下:

window.jamDom = {}
jamDom.getSiblings = function (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
}

jamDom.addClass = function (node,classes){
  classes.forEach( (value)=> node.classList.add(value) )
}


jamDom.getSiblings(item3)
jamDOm.addClass(item3 , ['a','b','c'])

如果我们想要用

item3.addClass( ['a','b','c'] )

这种形式,应该怎么做呢?

有两种方法,方法一:直接改node的原型

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

console.log(item3.getSiblings())
item3.addClass(['a','b','c'])

//用call更加直观的了解
//item3.getSiblings.call(item3)
//item3.addClass.call(item3,['a','b','c'])

方法二,不要改Node原型

window.jQuery = function (node){
  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.forEach( (value)=> node.classList.add(value) )
    }
  }
}

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