《锋利的jQuery》十、jQuery插件的写法


title: 《锋利的jQuery》十、jQuery插件的使用和写法
date: 2017-07-24 06:20:00
tags: 锋利的jQuery


编写插件的目的是给已有的一系列方法或函数做一个封装,以便在其他地方重复使用,方便后期维护和提高开发效率。

插件的种类

1.封装对象方法的插件

这种插件是将对象方法封装起来,用于通过选择器获取jQuery对象进行操作,是最常见的一种插件。比如parent()appendTo()addClass()等。

2.封装全局函数的插件

可以将独立的函数加载到jQuery的命名空间之下。例如$.ajax()$.trim()等。

3.选择器插件

个别情况下,会需要使用到选择器插件,虽然jQuery的选择器十分强大,但还是会需要扩充一些自己喜欢的选择器。

插件的基本要点

插件的文件名推荐命名为jquery.[插件名].js

所有的对象方法都应该附加到jQuery.fn对象上,而所有的全局函数都应该附加到jQuery对象本身上。

在插件内部,this只想的是当前通过选择器获取的jQuery对象,例如click()方法指向的是DOM元素。可以通过this.each来遍历所有元素。

插件应该返回一个jQuery对象,以保证插件的可链式操作。除非插件需要返回的是一些需要获取的量,例如字符串或者数组。

避免在插件内部使用$作为jQuery对象的别名,而应该用完整的jQuery来表示。这样可以避免冲突,如果使用$作为jQuery的别名,要用必报来避免冲突。

插件中的闭包

利用闭包的特性,既可以避免内部临时变量影响全局空间,又可以在插件内部继续使用$作为jQuery别名。

(function($){        // 将$作为匿名函数的形参
    // 这里编写插件的代码
    var foo;
    var bar = function(){
          // 在匿名函数内部的函数都可以访问foo,即便是在匿名函数的外部调用bar()的时候,也可以在bar()的内部访问到foo,但在匿名函数的外部直接访问foo是做不到的。
    }

    // 下面的语句让匿名函数内部的函数bar()返回到全局可访问的范围内,这样就可以在匿名函数的外部通过调用jQuery.BAR()来访问内部定义的函数bar(),并且内部函数bar()也能访问匿名函数内的变量foo。
    $.BAR = bar;
})(jQuery)        // jQuery作为实参传递给匿名函数

jQuery的插件机制

jQuery提供了两个用于扩展jQuery功能的方法,jQuery.fn.extend()方法和jQuery.extend()方法。第一个方法用于封装对象方法的插件,第二个适用于封装全局函数插件和选择器插件。这两个方法都接收一个参数,类型是Object。

jQuery.extend()除了扩展插件能用到,还有一个用处是扩展已有的对象,也就是传递两个参数,类型都是object,第二个对象会和第一个对象合并,相同的属性第二个会覆盖第一个。

var settings = { validate: false , limit: 5 , name: 'foo' };
var options = { validate: true , name: 'bar' };
var newObj = jQuery.extend(settings,options);
console.log(newObj)      // { validate: true , limit: 5 , name: 'bar' }

所以jQuery.extend()方法经常用于设置插件方法的一些默认参数。

编写jQuery插件

封装jQuery对象插件

设置和获取颜色的插件

首先编写设置和获取颜色的插件color。该插件的功能是:

  1. 设置匹配元素的颜色
  2. 获取匹配的元素(元素集合中的第一个)的颜色。

由于是在jQuery对象上扩展方法所以使用jQuery.fn.extend,这里要注意的是插件扩展内部的this指的是jQuery对象而不是普通的dom对象,然后插件如果不是返回字符串之类的特定值,应当使其具有可链接性,为此要直接返回这个this对象。

(function($){
    $.fn.extend({
        'color': function(value){
            if(value == undefined){      
                return this.css('color');      // 获取颜色。css方法本身就默认返回第一个的颜色
            }else{        
                return this.each(function(){
                    $(this).css('color',value);     // 设置颜色,由于this是jQuery对象,所以不需要each遍历
                })
            }
        }
    });
})(jQuery)

表格隔行变色插件

(function($){
    $.fn.extend({
        'alterBgColor': function(options){
            options = $.extend({
                odd: 'odd',        // 偶数行样式
                even: 'even',      // 奇书行样式
                selected: 'selected'       // 选中行样式
            },options);
            $('tbody>tr:odd' , this).addClass(options.odd);
            $('tbody>tr:even' , this).addClass(options.even);
            $('tbody>tr' , this).click(function(){
                // 判断当前是否选中
                var hasSelected = $(this).hasClass(options.selected);
                // 如果选中,则移出selected类,否则就加上selected类
                $(this)[hasSelected ? 'removeClass' : 'addClass'](options.selected).find(':checkbox').prop('checked',!hasSelected);
             });
             // 如果单选框默认情况下是选择的,则高亮
             $('tbody>tr:has(:checked)' , this).addClass(options.selected);
             return this;       // 返回this,可以继续链式操作
        }
    });
})(jQuery)

需要注意的是上面两个插件内部this都是可以匹配多个元素,但是如果遇到只能匹配一个元素的时候,要each遍历匹配的jQuery对象,而在each内部,this就是dom对象不是jQuery对象了。

封装全局函数

这类插件是在jQuery命名空间内部添加一个函数。

增加两个函数,用于去除左侧空格和右侧空格。

(function($){
    $.extend({
        ltrim: function(text){
            // 假如text是undefined等非正确参数,就取空字符串,防止replace方法报错
            return (text || '').replace(/^\s+/g,'');
        },
        rtrim: function(text){
            return (text || '').replace(/\s+$/g,'');
        }
    })
})(jQuery)

由于是全局函数,所以要由jQuery或者$调用,不能用jQuery对象去调用。

$.ltrim('         text');
$.rtrim('text        ');

自定义选择器

jQuery提供了一套方法让用户客户以通过制作选择器插件来使用自定义选择器。jQuery选择器执行的步骤如下:

  1. jQuery的选择符解析器首先会使用一组正则表达式来解析选择器

  2. 针对解析出的每个选择符执行一个选择器函数

  3. 根据这个函数返回的是true还是false来决定是否保留这个元素。

按照上面的步骤,以$('div:gt(1)')来举例:

  1. 选择器首先获取所有的div元素

  2. 逐个将这些div元素作为参数,连同括号里的1等一些参数一起传递给gt对应的选择器函数进行判断

  3. 如果gt对应的选择器函数返回true则这个div元素保留,如果返回false则不保留,这样得到的结果就是一个符合要求的div元素集合

现在来看一下最关键的gt的选择器函数:

gt: function(a,i,m){
     return i > m[3] - 0;
}

选择器一共接受三个参数:

第一个参数为a,指向的是当前遍历到的dom元素。

第二个参数为i,指的是当前遍历到的dom元素的索引值,从0开始。

第三个参数m最为特别,它是由jQuery正则解析引擎进一步解析后的产物(用match匹配出来的),m是一个数组。在这时m[3]的值就是'1'。
m[0]的值是:gt(1)
m[1]的值是:
m[2]的值是gt
m[4]在上面的例子没有体现,假如是div:l(ss(dd))这样一个选择器,m[4]就指向了(dd)这部分,另外这里的m[3]的值就是ss(dd)

编写一个between选择器

例如使用$('div:between(2,5)')能实现获取索引3、4元素的功能。

选择器仅仅是jQuery.expr[':']对象的一部分,所以这里是将between函数扩展到jQuery.expr[':']对象中。

(function($){
    $.extend(jQuery.expr[':'],{
        between: function(a,i,m){
            var tmp = m[3].split(',');    // 将m[3]'最小值,最大值'改为['最小值','最大值']
            return tmp[0] - 0 < i && i < tmp[1] - 0;      // 将索引与最小和最大值进行比较,符合要求的返回true,这里-0 是隐式转换的意思
        }
    })
})(jQuery)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 原文链接 http://blog.poetries.top/2016/10/20/review-jQuery 关注...
    程序员poetry阅读 16,584评论 18 503
  • 1.JQuery 基础 改变web开发人员创造搞交互性界面的方式。设计者无需花费时间纠缠JS复杂的高级特性。 1....
    LaBaby_阅读 1,285评论 0 2
  • (续jQuery基础(1)) 第5章 DOM节点的复制与替换 (1)DOM拷贝clone() 克隆节点是DOM的常...
    凛0_0阅读 1,268评论 0 8
  • 二期学员行雨第11天作业。 1.你是如何看待觉悟的?你满意自己的现状吗? 咋一看,标题就很让人醍醐灌顶。“很多人一...
    百龄语阅读 217评论 0 0
  • 中秋节有悠久的历史,和其它传统节日一样,也是慢慢发展形成的,古代帝王有春天祭日,秋天祭月的礼制,早在《周礼》一书中...
    上官书函阅读 310评论 0 5