总结简化版jQuery

自己封装两个函数

封装函数的方法。这两个函数分别为:

function getSiblings(node){}

getSiblings 函数的功能为获取传入节点的所有"兄弟",结果返回一个包装好的对象 以及函数:addClass

function addClass(node,classes){}

此函数的功能为:对节点添加或删除class,传入一个节点和一个对象如:{a:true,b:false,c:true}
当传入对象的value值为true则表示在node的classList中添加它的key,如果为false,则表示在node的classList中删除key。

代码如下:

function getSiblings(node){
        // children 与 childNodes的区别:
        // 非IE浏览器下 childNodes为获取元素节点与文本节点
        // children则是获取元素节点,且浏览器表现相同
        var allChildren = node.parentNode.children;
        var array = {
            length:0
        }
        for(var i=0;i<allChildren.length;i++){
            if(allChildren[i]!==node){
                array[array.length] = allChildren[i];
                array.length += 1;
            }
        }
        return array;
    }
function addClass(node,classes) {
        for(var key in classes){
            if(classes[key]){
                node.classList.add(key);
            }else{
                node.classList.remove(key);
            }
        }
    }

代码优化

对于函数addClass 可以进行代码优化,如果不考虑性能,仅从代码的“美观度”来讲,优化原则其实非常简单即:
如果在代码中,存在类似的代码,就说明代码存在优化的可能。
函数addClass中,存在类似的代码node.classList.add(key);以及node.classList.remove(key); 优化后的代码如下:

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

命名空间

将一个对象封装好函数,设置到全局对象window当中,这就是所谓的命名空间。代码如下:

var item3 = document.getElementById('item3');
    window.chDom = {};
    chDom.getSiblings = function(node){
        var allChildren = node.parentNode.children;
        var array = {
            length:0
        }
        for(var i=0;i<allChildren.length;i++){
            if(allChildren[i]!==node){
                array[array.length] = allChildren[i];
                array.length += 1;
            }
        }
        return array;
    }
    chDom.addClass = function(node,classes){
        for(var key in classes){
            var value = classes[key];
            var methodName = value?'add':'remove';
            node.classList[methodName](key);
        }
    }
    // 当我们建立了一个"命名空间",如示例的 chDom ,这个对象将函数封装了起来
    // 调用时我们只需要按照如下调用即可:
    console.log(chDom.getSiblings(item3));
    chDom.addClass(item3,{a:true});

使用Node.prototype

当我们想调用getSiblings与addClass时,如果每一次都这样去调用我们的API:chDom.getSiblings(node);,
我们难免会觉得这样写代码都有一点臃肿,如果代码是node.getSiblings(),那么就最好不过了,不仅简洁,
而且更容易让人明白代码的“语意”。使用Node的原型就可以做到这一点:

 Node.prototype.getSiblings = function(){
        var allChildren = this.parentNode.children;
        var array = {
            length:0
        }
        for(var i=0;i<allChildren.length;i++){
            if(allChildren[i] !== this){
                array[array.length] = allChildren[i];
                array.length += 1;
            }
        }
        return array;
    }
    Node.prototype.addClass = function(classes){
        for(var key in classes){
            var value = classes[key];
            var methodName = value?'add':'remove';
            this.classList[methodName](key);
        }
    }

我们将getSiblings以及addClass 添加到了Node的原型当中,这样一来,我们就可以使用node.getSiblings()这样的写法来调用我们封装好的函数。

this是call()的第一个参数

this是什么?this就是call()的第一个参数,没有然后了。回顾下call():call(this,arguments[0],arguments[1],...arguments[n])。
对于item3.getSiblings.call(item3) 即相当于 :item3.getSiblings() 为什么要使用call()?
因为,不使用call()的话,你怎么会理解this呢?试想一下这段代码打印的结果是什么?

console.log(item3.getSiblings.call(item4));

打印在控制台上的结果为:

Object
0: li#item1
1: li#item2
2: li#item3
3: li#item5
length: 4
 __proto__: Object

当使用call里面的第一个参数为item4时,this代表的就是item4了,打印出来的结果自然是除了item4以外的其他li节点包装的对象。所以只有使用call,你才会明白this到底是什么东西

简易的jQuery

使用Node.prototype固然可以,但是试想一下,张三在Node原型里添加了某某属性,李四又在Node原型里面添加了某某属性,你填了一撇,我写了一捺,这样一来,岂不是全都乱掉了吗?于是乎,我们可以这样做。

    // 继Node.prototype后,我们将jQuery这个属性添加到window这个全局对象当中
    // var node = jQuery(argument);向 jQuery这个函数中传入的参数可以是节点或者是选择器(字符串);函数返回一个对象
    // 对象中有 addClass,text等属性,这些属性对应了上节课所实现的函数;对于getSiblings()这个方法实现起来相对比较复杂,所以先忽略这个方法
    window.jQuery = function (nodeOrSelector) {
        let nodes = {};
        if(typeof nodeOrSelector === 'string'){
            var temp = document.querySelectorAll(nodeOrSelector);
            for(var i=0;i<temp.length;i++){
                nodes[i] = temp[i];
            }
            nodes.length = temp.length;
        }else if(nodeOrSelector instanceof Node){
            nodes[0] = nodeOrSelector;
            nodes.length = 1;
        }
        // 函数addClass与函数外的变量nodes形成了一个闭包
        nodes.addClass = function(classes){
            for(var key in classes){
                var value = classes[key];
                var methodName = value? 'add':'remove';
                for(var i=0;i<nodes.length;i++){
                    nodes[i].classList[methodName](key);
                }
            }
        }
        // 函数text与函数外的变量 nodes形成了一个闭包
        nodes.text = function (text) {
            // 如果text函数什么都没有传入 则表示获取textContent
            if(text === undefined){
                var texts = [];
                for(let i=0;i<nodes.length;i++){
                    texts.push(nodes[i].textContent);
                }
                // 务必要将nodes这个对象返回~~
                return texts;
            }else{
                // 如果text函数传入了值,则表示将textContent的值设置为传入的值
                // 会将获取到的element所有的值都变为 传入的值
                for(let i=0;i<nodes.length;i++){
                    nodes[i].textContent = text;
                }
            }
        }
        // 务必要将nodes这个对象返回~~
        return nodes;
    }
    var node = jQuery('ul>li');
    console.log(node.text());
    node.text.call(node,'hi');
    node.addClass.call(node,{'red':true});

上面就是个简易的jQuery,当然jQuery可远远没有这么简单。不过,通过上面的代码最起码可以了解到jQuery是什么,那么,jQuery到底是什么?

jQuery其实就是一堆javaScript的函数,因为原生Dom提供的API太垃圾了,所以jQuery将我们常用的一些功能进行了封装,方便我们来调用,
提高开发的效率,jQuery这个js库应用最为广泛,于是乎成为了行业的标准。所以说jQuery的本质就是个调用了DomAPI的函数库。

初探jQuery

jQuery引入地址:https://cdnjs.com/

前端参考文档手册(中文):http://cndevdocs.com/

jQuery addClass:

    var nodes = jQuery('ul>li');
    // jQuery addClass 支持两种方法
    // 1  .addClass( className )
    // 示例:
    // nodes.addClass('red');
    // 2  .addClass( function(index, currentClass) )
    // 示例:
    /*nodes.addClass((index,currentClass)=> {
        if(index<3){return 'red'};
    })*/
    // 3  jQuery支持链式操作
    // 示例:
    var classes = ['red','green','yellow','blue','black'];
    nodes.removeClass('red').addClass(function (index,currentClass) {
        return classes[index];
    })

jQuery toggleClass:

    var nodes = jQuery('ul>li');
    btn.onclick = function () {
        // toggle的含义为:开关,切换
        // 如果nodes有red这样的class则删除,如果没有则添加
        nodes.toggleClass('red');
    }

jQuery 优点 与 $符号建议

jQuery 的优点有:

jQuery 在兼容性方面做得很好,1.7 版本兼容到 IE 6
jQuery 还有动画、AJAX 等模块,不止 DOM 操作
jQuery 的功能更丰富
jQuery 使用了 prototype,我们没有使用,等讲了 new 之后再用

$符号的建议:

window.$ = jQuery

在jQuery中,$符号可以替代jQuery,如声明一个jQuery的对象:var nodes = jQuery('ul>li');。我们可以写成:var $nodes = $('ul>li');
这里面,注意,我将原本的nodes变为了$nodes。这当然不是强制要求,但是我们确实应该这么做,这样我们的代码才便于维护,这样我们才能知道,哪些是jQuery对象。

作业查看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352