美文网首页
仿写 jQuery

仿写 jQuery

作者: simplue | 来源:发表于2018-11-19 21:31 被阅读0次

    在 jQuery 中,要为特定元素添加 class 很方便,只需要使用调用addClass方法即可,例如为所有 div 添加 一个叫 red 的 class 只需要写 $("div").addClass("red")。这与使用浏览器 api 实现同样的功能相比要简洁明了不少。本文通过逐渐改进的方式,实现一个从调用角度上与其类似的 api。

    首先,先使用最直接的方式实现功能,传入一组节点和一个类名,为这组节点添加这个类

    addClass = function (nodes, className) {
      nodes.forEach(function (el) {
        el.classList.add(className)
      })
    }
    
    let nodes = document.querySelectorAll('div')
    addClass.call(undefined, nodes, 'red')
    

    这个方式有个缺点是只能一次添加一个类,如果需要添加多个则需要调用多次,不太方便。因为我们可以借助函数中的arguments获取到传入的所有(非this)参数,所以 className 这个参数也可以舍去,下面是可以一次性添加多个类的实现。

    addClass = function (nodes) {
      let args = arguments
      nodes.forEach(function (el) {
        for (let i = 1; i < args.length; i++) {
          el.classList.add(args[i])
        }
      })
    }
    
    let nodes = document.querySelectorAll('div')
    addClass.call(undefined, nodes, 'red', 'foo')
    

    对比 jQuery 中的实现可以发现,这里每次都要先获取到节点然后再操作,而使用 jQuery 则一般直接传入选择器。所以这里可以进一步改造,使其适应选择器和节点参数。

    addClass = function (nodeOrSelector) {
      let args = arguments
      if (typeof nodeOrSelector === 'string') {
        nodes = document.querySelectorAll(nodeOrSelector)
      } else {
        nodes = nodeOrSelector
      }
      nodes.forEach(function (el) {
        for (let i = 1; i < args.length; i++) {
          el.classList.add(args[i])
        }
      })
    }
    
    addClass.call(undefined, 'div', 'red', 'foo')
    

    到这里,实际上与 jQuery 的 api 已经有几分相似之处了,但是这里有一个明显的问题,那就是如果用户自己也定义了一个 addClass,那么我们的 addClass 就会被覆盖掉。因此,我们应该创建一个“独立的区域”用来存放这个函数。

    window.$ = {
      addClass: function (nodeOrSelector) {
        let args = arguments
        if (typeof nodeOrSelector === 'string') {
          nodes = document.querySelectorAll(nodeOrSelector)
        } else {
          nodes = nodeOrSelector
        }
        nodes.forEach(function (el) {
          for (let i = 1; i < args.length; i++) {
            el.classList.add(args[i])
          }
        })
      }
    }
    
    $.addClass.call(undefined, 'div', 'red', 'foo')
    

    改完以后和 jQuery 更像了,就差最后几步了。实际上,如果我们执行typeof $(在引入了 jQuery的前提下),可以发现它实际上是个函数。也就是说其实应该模仿它,将上面的代码也封装成一个函数。完成后的完整代码如下:

    // index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .red {color: red; background-color: black;}
        </style>
    </head>
    <body>
    <div>DIV1</div>
    <div>DIV2</div>
    <div>DIV3</div>
    <script src="./main.js"></script>
    </body>
    </html>
    
    // main.js
    window.jQuery = function (nodeOrSelector) {
      let nodes
    
      if (typeof nodeOrSelector === 'string') {
        nodes = document.querySelectorAll(nodeOrSelector)
      } else {
        nodes = {
          0: nodeOrSelector,
          length: 1,
        }
      }
    
      nodes.addClass = function () {
        let classArray = arguments
        nodes.forEach(function (el) {
          for (let className of classArray ){
            el.classList.add(className)
          }
        })
      }
    
      return nodes
    }
    
    window.$ = window.jQuery
    
    setTimeout(function () {
      let $div = $('div')
      $div.addClass('red', 'foo', 'bar')
    }, 1000)
    

    相关文章

      网友评论

          本文标题:仿写 jQuery

          本文链接:https://www.haomeiwen.com/subject/hetzfqtx.html