[JavaScript]从DOM到jQuery(1)

最近学习到了jQuery的内容,从DOM到jQuery之间,到底发生了什么变化,怎么从DOM转变到jQuery,他们之间存在什么联系和区别,这篇博文梳理一下初入门学习jQuery的一些思路和分析过程。

这是jQuery官方网站和中文文档

假设现在我们有这样的一个HTML结构:

<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>
.red {
    color: red
}
.fontSize {
    font-size: 20px;
}

1.用DOM获取一个元素节点并设置样式

item3.classList.add('red')
item3.classList.add('fontSize')

2.进行函数封装

给代码进行封装,提高代码复用率和健壮性,同时加入判断:如果传入的参数是一个字符串,那就为这个元素添加样式;如果传入的参数是一个数组,那么就为这个元素增加这个数组中的样式。

function addClass(node,classes){
    if(typeof classes === 'string'){
        node.classList.add(classes)
    }else if(Array.isArray(classes)){
        for(let i=0;i<classes.length;i++){
            node.classList.add(classes[i])
        }
    }else{
        alert('请输入一个字符串或者数组来表示你所要设置的样式名称')
    }
}
addClass(item3,['red','fontSize'])
addClass(item3,'red')

命名空间

关于命名空间更详细的文章

由于JavaScript没有文件作用域,不同的函数分散在不同的文件中,甚至由不同的人编写,重名的概率大大增加。是不是足够小心就可以了呢?也不尽然,还有些意外情况,比如经常会用到继承,于是写了一个没出现过的函数名extend,不料在EcmaScript5中加入了extend函数,命名空间的必要性就体现出来了。
JavaScript有函数的作用域,可以利用这点把自定义的函数写到一个函数体内,这样函数内的变量、对象、函数就像在一个命名空间内一样和外部隔离。

我们给刚刚创建的函数一个命名空间,以避免和其他的函数起冲突:

window.dom = {}

dom.addClass = addClass

dom.addClass(item3,['red','fontSize'])

更直观的使用方式

但是,为了更加直观和符合语法认知,如果我们要实现类似于这种方法:
item3.addClass(['red','fontSize'])
该怎么办呢?

两种方法:

  • 将这个方法添加进公有属性(prototype)中
Node.prototype = function addClass(node,classes){
    if(typeof classes === 'string'){
        node.classList.add(classes)
    }else if(Array.isArray(classes)){
        for(let i=0;i<classes.length;i++){
            node.classList.add(classes[i])
        }
    }else{
        alert('请输入一个字符串或者数组来表示你所要设置的样式名称')
    }
}
item3.addClass(['red','fontSize'])
// 等价于 item3.addClass.call(item3,['red','fontSize'])

缺点:容易覆盖原型中的方法,造成混乱。

  • 改造成构造函数,返回一个拥有自定义方法的对象
window.Node2 = function(node){
    return {

        addClass: function(node,classes){
            if(typeof classes === 'string'){
                node.classList.add(classes)
            }else if(Array.isArray(classes)){
                for(let i=0;i<classes.length;i++){
                    node.classList.add(classes[i])
                }
            }else{
                alert('请输入一个字符串或者数组来表示你所要设置的样式名称')
            }
        }
    }
}
var node2 = Node2(item3)
node2.addClass(['red','fontSize'])

node2通过传入一个参数给Node2的函数,返回了一个新的对象,这个对象里面有我们自己定义的方法,然后我们就可以使用这些方法和属性操作这个节点。

我们再把命名改一下,发现他越来越接近jQuery了:

window.jQuery = function(node){
    return {

        addClass: function(node,classes){
            if(typeof classes === 'string'){
                node.classList.add(classes)
            }else{
                classes.forEach((value) => {
                    node.classList.add(value)
                    })
                }
            }
        }
    }
}
var node2 = jQuery(item3)
node2.addClass(['red','fontSize'])

这就是怎么从DOM改造成jQuery的思路,jQuery操作比DOM更方便,效率更高。

优化代码

接下来优化一下代码:如果我们接收的参数不是一个id选择器,而是一个字符串呢?(如我们不只要给item3添加样式,而是要给这个ul里全部的li添加样式,该怎么做呢?)

window.jQuery = function(nodesOrSelector){
    let nodes = {}
    //判断传入参数是否为字符串
    if (typeof nodesOrSelector === 'string'){
        let temp = document.querySelectiorAll(nodesOrSelector)
        for (let i = 0;i<temp.length;i++){
            nodes[i] = temp[i]
        }
    //如果传入的参数是一个节点
    } else if(nodeOrSelector instanceof Node){
        nodes = {0:nodeOrSelector,length:1}
    }
    nodes.addClass = function(classes){
        if(typeof classes === 'string'){
            for(let i=0;i<nodes.length;i++){
                nodes[i].classList.add(classes)
            }
        }else if(Array.isArray(classes)){
            classes.forEach((value) => {
                for(let i = 0;i<nodes.length;i++){
                    nodes[i].classList.add(value)
                }
            })
        }else{
            alert('请输入一个字符串或者数组来表示你所要设置的样式名称')
        }
    }
    return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['red','fontSize'])

小结

这就是jQuery的模式:jQuery实际上是一个构造函数,接受一个参数,这个参数有可能是节点,然后返回一个方法对象去操作节点。(接受一个元素,生成一个新的对象,这个新的对象有新的API)

原文地址:https://www.cnblogs.com/No-harm/p/9555070.html