zoukankan      html  css  js  c++  java
  • [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)

  • 相关阅读:
    No binary for PhantomJS browser on your platform. Please, set "PHANTOMJS_BIN"
    用MeanJS和Yeoman生成器生成【翻译】
    Angular中在前后端分离模式下实现权限控制
    HierarchyId 与.Net Framework 4.5.3报错
    AngularUI Router 概要【转】
    SpecFlow使用入门【转】
    使用AutoMapper实现Dto和Model的自由转换(下)【转】
    使用AutoMapper实现Dto和Model的自由转换(中)【转】
    使用AutoMapper实现Dto和Model的自由转换(上)【转】
    有jQuery背景,该如何用AngularJS编程思想?
  • 原文地址:https://www.cnblogs.com/No-harm/p/9555070.html
Copyright © 2011-2022 走看看