像 jQuery 一样封装 API

2018-12-03  本文已影响0人  Liveup

一、前言

jQuery 作为 JavaScript 函数库,是一种特定种类的API。它的功能强大而丰富,帮助解放了DOM API。即使在如今框架盛行的时代,仍然值得我们学习。
在正式学习使用 jQuery API 之前,让我们仿造其形式试着自己封装两个 API 。

二、实现目标

封装 addClass、setText 两个函数,实现
① 为元素批量添加类
② 设置元素中的文本内容

var $div = $('div')
$div.addClass('red') // 可将所有 div 的 class 添加一个 red
$div.setText('hi') // 可将所有 div 的 textContent 变为 hi

三、步骤

1. 封装三个好用的函数 getSiblings、addClass、setText。
// 匹配 节点node
function getSiblings(node) {
    var allChildren = node.parentNode.children
    var arr = { length: 0 }
    for (let i in allChildren) {
        if (allChildren[i] != node) {
            arr[arr.length] = allChildren[i]
            arr.length += 1
        }
    }
    return arr
}

function addClass(node, thoseClass) {
    // 参数 thoseClass 支持字符串和数组
    if(typeof thoseClass === 'string') {
        node.classList.add(thoseClass)
    }else if(Array.isArray(thoseClass)) {
        thoseClass.forEach( value => node.classList.add(value) ) 
    }
}

function setText(node, content) {
    node.textContent = content
}

console.log( getSiblings(node) )
addClass(node, ['red', 'big', 'center'])
setText(node, 'hi')

使用命名空间,如库YUI

xinDom = { 
    addClass: function(node, thoseClass) {
        // 参数 thoseClass 支持字符串和数组
        if(typeof thoseClass === 'string') {
            node.classList.add(thoseClass)
        }else if(Array.isArray(thoseClass)) {
            thoseClass.forEach( value => node.classList.add(value) ) 
        }
    },
    setText: function (node, content) {
        node.textContent = content
    }
}
xinDom.addClass(node, ['red', 'big', 'center'])
xinDom.setText(node, 'hi')
2. 节点node 放到前面调用
1)扩展Node接口。将函数添加到 节点原型(Node.prototype)中,则节点node可直接调用
Node.prototype.addClass = function(thoseClass) {
    // 使用 this 得到 节点node
     if(typeof thoseClass === 'string') {
        this.classList.add(thoseClass)
    }else if(Array.isArray(thoseClass)) {                         
        thoseClass.forEach( value => this.classList.add(value) )        
    }
}

Node.prototype.setText = function(content) {
    this.textContent = content
}

node.addClass.call(node, 'red') // 或 node.addClass('red')
node.setText.call(node, 'hi')   // 或 node.setText('hi')
2)使用新的接口。创建一个构造函数 jQuery,返回封装了自有API的对象
// 匹配 节点node 或 选择器
window.jQuery = function(nodeOrSelector) {

    var nodes = {}
    if(typeof nodeOrSelector === 'string') {
        
        var tmp = document.querySelectorAll(nodeOrSelector)
        nodes.length = tmp.length
        for(var i=0; i<tmp.length; i++) {
            nodes[i] = tmp[i]
        }

    }else if(nodeOrSelector instanceof Node) {
        nodes = {
            0: nodeOrSelector,
            length: 1
        }
    }

    return {
        elements: nodes,
        addClass: function(thoseClass) {

            if(typeof thoseClass === 'string') {
                for(var i=0; i<nodes.length; i++) {
                    nodes[i].classList.add(thoseClass)
                }
            }else if(Array.isArray(thoseClass)) {
                for(var i=0; i<nodes.length; i++) {                            
                    thoseClass.forEach( value => nodes[i].classList.add(value) )
                }
            }

        },
        setText: function(content) {                    

            for(var i=0; i<nodes.length; i++) {
                nodes[i].textContent = content
            }
            
        }
    }
}

jQuery('div').setText('hi')
3. 使用缩写,$ 指代 jQuery
window.$ = jQuery

var $div = $('div')
$div.addClass('red') // 可将所有 div 的 class 添加一个 red
$div.setText('hi')

四、jQuery 只是这样?

窥探了 jQuery 本质,它的强大并不仅限如此,jQuery 函数库的优点概括:

  1. 兼容性方面做得很棒。
  2. 不止提供了便捷的 DOM 操作,还有动画、Ajax等丰富的功能。
  3. jQuery 不仅使用了 prototype,还使用了 new(还未学到)。
上一篇下一篇

猜你喜欢

热点阅读