通过自己造API来理解jquery吧

先造两个小轮子


我们先造两个函数, 用来简化我们DOM操作

获取所有兄弟节点

function getSiblings(node) {
  let target = node.parentNode.children
  let siblings = {length:0}
  for(let i=0; i



批量增加删除class

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

在我们写代码的时候, 如果出现类似的代码, 就有优化的可能

上面第二个例子, 我们发现if里面的两句很像, 我们考虑下能不能优化下呢

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

我们可以优化为

let methodName = classes[key] ? 'add' : 'remove'
node.classList[methodName](key)

优化后的代码

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


命名空间


接下来把两个函数包装下, 让别人知道他俩是一个家族的, 都是用来操作DOM的, 这里为了简单化, 就不用原型链或者类的方法来写了

window.ssdom = {}
ssdom.getSiblings = getSiblings
ssdom.addClass = addClass

上面这种给函数加个前缀的方法就是命名空间

这样我们就可以继续优化我们的代码

window.ssdom = {}

ssdom.getSiblings = function(node) {
  let target = node.parentNode.children
  let siblings = {length:0}
  for(let i=0; i

这种设计模式的优点

  1. 命名更直观, 更容易理解
  2. 避免变量覆盖


直接使用元素对象调用函数


但是这样还是有一丢丢麻烦, 我们可不可以直接用节点调用函数呢?

我们来试试吧, 这里我们想到了两种方法

方法一:

我们给Node的原型创建一个getSiblingsaddClass方法, 那么所有node对象都可以继承这两个方法了

Node.prototype.getSiblings = function() {
  let target = this.parentNode.children
  let siblings = {length:0}
  for(let i=0; i

这样就可以直接用节点调用了

假设我们有下面html

  
  • 选项1
  • 选项2
  • 选项3
  • 选项4
  • 选项5

我们可以直接用node节点调用

item3.getSiblings()
item4.addClass({a:true, c:false, b:true})



但是这也有个问题, 如果别人已经在原型定义过同名函数, 那么我们就会覆盖别人的方法,为了避免我们覆盖别人的方法, 我们用另外一种方法试试

方法二:

我们自己造一个函数, 把它叫做jQuery, 然后把node传给这个函数, 这个函数返回一个对象, 对象里面包含上面两个方法, 这样就不会出现覆盖原先的方法的情况了

 function jQuery(node) {
  return {
    getSiblings: function() {
      let target = node.parentNode.children
      let siblings = {length:0}
      for(let i=0; i

这个方法就解决了第一种方法会覆盖别人同名方法的问题



上面的代码, 我们只能传一个节点, 我们再稍微增加一点儿功能, 我们让它也可以接收一个字符串

function jQuery(nodeOrSelector) {
  /*************增加接收string类型选择器功能******************/
  let node
  if(typeof nodeOrSelector === 'string') {
    node = document.querySelector(nodeOrSelector)
  }else {
    node = nodeOrSelector
  }

  /*******************原来的代码********************/
  return {
    getSiblings: function() {
      let target = node.parentNode.children
      let siblings = {length:0}
      for(let i=0; i


增加一次选择多个元素功能

再来继续完善功能, 我们来让他可以一次可以选择多个node, 并增加一些有用的API

function jQuery(nodeOrSelector) {
  let nodes = {}
  if(typeof nodeOrSelector === 'string') {

    /****将querySelectorAll获取的nodeList转换成纯伪数组***/
    let tmp = document.querySelectorAll(nodeOrSelector)
    for(let i=0; i li')

console.log($node2.text())

这里我们的jQuery就造完啦, 当然这个是超级山寨版的, 跟原版的根本比不了...

轮子造完啦


通过上面的例子, 我想告诉大家两点

  • 造轮子其实并没有大家想象的那么难, 但是造好用的轮子那就需要很深的功底了
  • jquery并没有那么高深莫测, 它其实就是将原生DOM方法进行了增强, 为了让我们更加方便的操作DOM

今天就讲到这里吧

你可能感兴趣的:(通过自己造API来理解jquery吧)