自己实现jQuery API

2018-10-16  本文已影响0人  阿龙哟

this 是call 的第一个参数!!!
this是call的第一个参数!!!
this是call的第一个参数!!!


<!DOCTYPE html>
<html>
<head>
<meta name="description" content="封装两个函数" />
  <meta charset="utf-8">
  <title>JS Bin</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>
</body>
</html>

封裝兩個函數:1.獲取相鄰元素,給偽數組添加元素
1.0版,虽然可以实现,但是在全局中定义这些函数可能会覆盖别人定义的函数

 //获取所有相邻元素
function getSiblings(node) {
    var allChildren = node.parentNode.children
    var siblings = {
      length: 0
    }
    for (let i = 0; i < allChildren.length; i++) {
      if (allChildren[i].id !== node.id) {
        siblings[siblings.length] = allChildren[i] //给伪数组添加元素
        siblings.length += 1
      }
    }
    return siblings
  }

  var classes = {
    a: true,
    b: false,
    c: true
  }
  
  
  //添加类名
  function addClass(classes,node) {

    for (let key in classes) {
      if (classes[key]) {
        node.classList.add(key)
      } else {
        node.classList.remove(key)
      }
    }
  }

addClass.call(undefined,classes,item1)

2.0版

//获取所有相邻元素
function getSiblings(node) {
   var allChildren = node.parentNode.children
   var siblings = {
     length: 0
   }
   for (let i = 0; i < allChildren.length; i++) {
     if (allChildren[i].id !== node.id) {
       siblings[siblings.length] = allChildren[i] //给伪数组添加元素
       siblings.length += 1
     }
   }
   return siblings
 }

 
 //添加类名
 function addClass(classes,node) {
   //代码优化准则,只要有相似代码,就一定可以优化
   for (let key in classes) {
     var value = classes[key]
     var method = value ? 'add':'remove'
     node.classList[method](key)
   }
 }
  
 window.along = {}
 along.getSiblings=getSiblings
 along.addClass = addClass
 console.log(along.getSiblings(item1))
 along.addClass({'a':true,'c':false},item1)
 
//设计模式 命名空间

定义一个名为along的对象空间,其中有两条函数属性,分别对应着这两个函数,使用的时候调用along里的函数,就可以避免覆盖别人函数的问题了,这种方法是一种设计模式名为命名空间

但是还是会有点问题,每次使用都要前缀名


3.0版
能不能直接用item来调用这两个办法,所以想到在原型上添加这两个方法

 //获取所有相邻元素
Node.prototype.getSiblings=function () {
    var allChildren = this.parentNode.children
    var siblings = {
      length: 0
    }
    for (let i = 0; i < allChildren.length; i++) {
      if (allChildren[i].id !== this.id) {
        siblings[siblings.length] = allChildren[i] //给伪数组添加元素
        siblings.length += 1
      }
    }
    return siblings
  }
  //添加类名
  Node.prototype.addClass=function(classes) {
    classes.forEach((value)=>this.classList.add(value))
  }
   
  console.log(item2.getSiblings())
item4.addClass(['a','b'])

4.0 版直接在原型上添加好像也有点问题,要是这个函数原来原型上就有了怎么办?所以从新构建一个Node2对象,,上面那种方法是通过this获取节点,这里我们直接传入一个node节点

window.Node2 = function(node) {
  return {
    getSiblings: function() {
      var allChildren = node.parentNode.children
      var siblings = {
        length: 0
      }
      for (let i = 0; i < allChildren.length; i++) {
        if (allChildren[i].id !== node.id) {
          siblings[siblings.length] = allChildren[i] //给伪数组添加元素
          siblings.length += 1
        }
      }
      return siblings
    },
    addClass: function(classes) {
      classes.forEach((value) => node.classList.add(value))
    }
  }
}

var node2 = Node2(item3)
console.log(node2.getSiblings(item2))
node2.addClass(['a','b'])

同时,把Node2改成jQuery,这个就是jQuery的模式了。给我旧的对象返回一个新的API,有新的方法


5.0版 改进传入的参数,如果是Node节点,就直接使用,如果是个选择器,则找到相对应的节点

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 siblings = {
        length: 0
      }
      for (let i = 0; i < allChildren.length; i++) {
        if (allChildren[i].id !== node.id) {
          siblings[siblings.length] = allChildren[i] //给伪数组添加元素
          siblings.length += 1
        }
      }
      return siblings
    },
    addClass: function(classes) {
      classes.forEach((value) => node.classList.add(value))
    }
  }
}

var node2 = jQuery('ul>li:nth-child(5)')
console.log(node2.getSiblings())
node2.addClass(['blue','a','b'])

升级版JQuery函数

window.jQuery = function(orderSelector) {
  let nodes = {}
  if (typeof orderSelector === 'string') {
    let temp = document.querySelectorAll(orderSelector)
    for (let i = 0; i < temp.length; i++) {
      nodes[i] = temp[i]
      nodes.length = temp.length
    }
  } else if (oederSelector instanceof Node) {
    nodes = {
      0: orderSelector,
      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) {
      let 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('ul>li')
node2.addClass(['red', 'blue'])
console.log(node2.text())
node2.text('tuesday')

模拟jQuery,实现了选择器,实现了添加类名,读取文本设置文本这几个
函数


再加个缩写

window.$ = jQuery
var node2 = $('ul>li')

Query 优点:
1.兼容性很好
2除了 DOM操作,还有动画,ajax
3.jQuery 的功能更丰富

上一篇下一篇

猜你喜欢

热点阅读