jQuery 插件的编写

一、jQuery 闭包

;(function($){
    //your code
})(jQuery);

闭包的好处:

  • 避免全局依赖
  • 避免第三方破坏
  • 兼容jQuery操作符'$'和jQuery

二、常用的jQuery 插件开发方式

1.直接给jquer添加全局函数

jQuery.alert = function(message){
    alert(message);
};

调用方法:

$.alert ('');

2.用extend()方法

extend是jquery提供的一个方法,把多个对象合并起来,参数是object

$.extend({
    test:function (opt) {
         alert(opt);
    }
})

调用方法:

$.test('');

3.通过向$.fn来向jquery添加方法

$.fn.myPlugin = function(){
    return this.each(function){
        //code
    }
};
/*这里$.fn === $.prototype*/
/*return this 返回当前对象,来维护插件的链式调用*/
/*each 循环实现每个元素的访问*/

调用方法:

$('div').myPlugin();

三、编写一个简单的插件

1、创建闭包,添加方法到jQuery对象中
/**
 * 使用js加载可折叠式控件
 */
(function ($) {
    /**
     * 添加方法到jQuery对象中
     * @param options 初始化时的object参数/调用方法是的string参数
     * @param para string参数,给内置方法传参
     */
    $.fn.foldGroup= function (options, para) {

    }
})(jQuery);
2、定义构造函数和内置方法
    /**
     *
     * @param element jQuery对象
     * @param options 初始化参数
     */
    function FoldGroup(element,options) {
        this.init();
    }

    FoldGroup.prototype = {
        init:function () {

        },
    }
3.初始化,字符串方法调用
    /**
     * 添加方法到jQuery对象中
     * @param options 初始化时的object参数/调用方法是的string参数
     * @param para string参数,给内置方法传参
     */
$.fn.foldGroup = function (options, para) {
        let $this = $(this),
            foldGroup = $this.data('foldGroup');
        //防止多次初始化
        if (!foldGroup) {
            foldGroup = new FoldGroup(this,options);
            $this.data('foldGroup', foldGroup);
        }

        // 如果是字符串则调用方法
        if($.type(options) === 'string') {
            return foldGroup[options](para);
        }
        return foldGroup;
    };
4、参数设置
   /**
     * 构造函数
     * @param element jQuery对象
     * @param options 初始化参数
     */
    function FoldGroup(element,options) {
        //当前的jQuery对象
        this.$element = $(element);
        this.style = {
            default:'panel-default',
            primary:'panel-primary',
            success:'panel-success',
            info:'panel-info',
            warning:'panel-warning',
            danger:'panel-danger',
        };

        //将初始化参数与默认参数合并
        this.config = $.extend({}, {
            id:$.getId('foldGroup'),
            fold:[
                {
                    style:'default',
                    title:'说明',
                    body:'这些只是简要说明',
                    expanded:false
                },
            ],
        },options || {});

        this.group = $('<div />',{'class':'panel-group','role':'tablist','aria-multiselectable':'true'})
            .attr('id',this.config.id);
        this.$folds = [];

        this.init();
    }
5、添加方法
      FoldGroup.prototype = {
        init:function () {
            let size = this.config.fold.length;
            for (let i = 0; i < size; i++) {
                let opt = this.config.fold[i];
                opt.index = i+1;
                let f = this.fold(opt);
                this.$folds.push(f);
                this.group.append(f.panel);
            }

            this.$element.append(this.group);
        },
        fold:function (opt) {

            let headId = $.getId('head'),
                collapseId = $.getId('collapse');

            let fold = {
                panel: $('<div />',{'class':'panel','index':opt.index}).addClass(this.style[opt.style]),
                head : $('<div />',{'class':'panel-heading','role':'tab'}).attr('id',headId),
                title : $('<h4 />',{'class':'panel-title'}),
                btnCollapse : $('<a />',{'role':'button','class':'collapsed','data-toggle':'collapse'
                    ,'data-parent':'#'+this.config.id,'href':'#'+collapseId,'aria-expanded':opt.expanded
                    ,'aria-controls':collapseId}).html(opt.title),
                collapse : $('<div />',{'class':'panel-collapse collapse','role':'tabpanel'
                    ,'aria-labelledby':headId}).attr('id',collapseId),
                body : $('<div />',{'class':'panel-body'}).html(opt.body)
            };

            if (opt.expanded) {
                fold.collapse.addClass('in')
            }

            fold.panel.append(
                fold.head.append(fold.title.append(fold.btnCollapse))
            ).append(fold.collapse.append(fold.body));
            fold.panel.data('opt',opt);
            return fold;
        },
        in:function (inner) {

            let size = this.$folds.length;

            for (let i = 0; i < size; i++) {
                let fold = this.$folds[i];
                if (fold.collapse.hasClass('in')) {
                    if (inner) {
                        return fold;
                    }
                    return fold.panel;
                }
            }
        },
        inBody:function (val) {
            let body = this.in(true).body;
            if (val) {
                body.html(val);
            }
            return body.html();
        },
        inStyle:function (val) {
            let panel = this.in(true).panel;
            let opt = panel.data('opt');
            if (val) {
                if (this.style.hasOwnProperty(val)) {
                    panel.removeClass(this.style[opt.style]);
                    panel.addClass(this.style[val]);
                    opt.style = val;
                }
            }
            return opt.style;
        },
        inTitle:function (val) {
            let title = this.in(true).btnCollapse;
            if (val) {
                title.html(val);
            }
            return title.html();
        },      
        inOpt:function(){
            let panel = this.in(true).panel;
            let opt = panel.data('opt');
            return opt;
        },
        folds:function () {
            return this.$folds;
        }
    };
6.使用实例
    /**
     * 初始化
     */
    $('#foldContainer').foldGroup({
        id:'foldGroupContainer',
        fold:[
            {
                style:'info',
                title:'说明',
                body:function () {
                    return $.btn({text:"取消",class:"btn btn-default",id:'off_1'})
                },
                expanded:true
            },
            {
                style:'info',
                title:'说明',
                body:function () {
                    return $.btn({text:"取消",class:"btn btn-default",id:'off_2'})
                },
                expanded:false
            }
        ]
    });
    /**
     * 点击后改变主题
     */
    $('#off_1').on('click',function () {
        let fold = $('#foldContainer').foldGroup('inStyle','success');
    });
    /**
     * 点击后更换内容
     */
    $('#off_2').on('click',function () {
        $('#foldContainer').foldGroup('inBody',function () {
            return [
                '<ul class="todo-list ui-sortable">',
                '<li>',
                '<span class="handle"><i class="fa fa-ellipsis-v"></i><i class="fa fa-ellipsis-v"></i></span>',
                '<input type="checkbox" value="">',
                '<span class="text">Design a nice theme</span>',
                '<small class="label label-danger"><i class="fa fa-clock-o"></i> 2 mins</small>',
                '<div class="tools">',
                '<i class="fa fa-edit"></i><i class="fa fa-trash-o"></i>',
                '</div></li>',
                '</ul>',
            ].join('')
        })
    });
7.参数说明

style:样式,包含default,primary,success,info,warning,danger

样式示例

expanded:是否默认展开,true or false
in(inner):返回当前展开的fold,参数inner为空时返回jQuery 对象,inner有值时返回初始化对象
inBody(val):获取/设置body
inStyle(val):获取/设置样式
inTitle(val):获取/设置title
inOpt():获取初始化设置
folds():获取所有fold初始化对象
例:

 /**
     * 初始化
     */
    $('#foldContainer').foldGroup({
        id:'foldGroupContainer',
        fold:[
            {
                style:'default',
                title:'default',
                body:function () {
                    return $.btn({text:"切换",class:"btn btn-primary",id:'off_1'})
                },
                expanded:true
            }
        ]
    });
    /**
     * 点击后改变主题
     */
    $('#off_1').on('click',function () {
        let fold = $('#foldContainer').foldGroup();
        //设置主题
        $('#foldContainer').foldGroup('inStyle','success');
        //获取当前主题
        alert(fold.inStyle());
        //设置title
        fold.inTitle(function () {
            return [
                'http://localhost:8080/index',
                '<div class="pull-right">',
                '<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>',
                '</div>'
            ].join('')
        })
    });

效果:


初始化

点击按钮


当前的样式

切换完成的效果

四、记录几个简单的插件

1.初始化bootstrap button 按钮的方法

代码:
/**
 * 初始化bootstrap按钮的方法
 */
(function ($) {
    $.extend({
        btn:function (opt) {
            let options = $.extend({}, {
                type: 'button',
                class: 'btn btn-primary',
                text: '确认',
            }, opt);
            return $('<button />', {'type': options.type, 'class': options.class ,'id':options.id})
                .html(options.text).click(options.click);
        }
    })
})(jQuery);
使用方式:
    let btn = $.btn({
                type:'button',
                class:'btn btn-primary',
                text: '确认',
                id:'bootstrap_button',
                click:function () {
                    alert('初始化bootstrap按钮的方法!')
                }
            });

将生成的jQuery对象添加到HTML中

<div id="test_plugin"></div>

$('#test_plugin').append(btn);
  • type: 按钮类型。buttonsubmitreset
  • class:样式。Bootstrap 提供的按钮样式有
<!-- Standard button -->
<button type="button" class="btn btn-default">(默认样式)Default</button>

<!-- Provides extra visual weight and identifies the primary action in a set of buttons -->
<button type="button" class="btn btn-primary">(首选项)Primary</button>

<!-- Indicates a successful or positive action -->
<button type="button" class="btn btn-success">(成功)Success</button>

<!-- Contextual button for informational alert messages -->
<button type="button" class="btn btn-info">(一般信息)Info</button>

<!-- Indicates caution should be taken with this action -->
<button type="button" class="btn btn-warning">(警告)Warning</button>

<!-- Indicates a dangerous or potentially negative action -->
<button type="button" class="btn btn-danger">(危险)Danger</button>

<!-- Deemphasize a button by making it look like a link while maintaining button behavior -->
<button type="button" class="btn btn-link">(链接)Link</button>
  • text:按钮中的文案,文字或html标签
  • id:按钮ID,非必填
  • click:点击事件,非必填

2.bootstrap模态框插件

代码:
/**
 * bootstrap模态框插件
 */
(function ($) {
    // 定义构造函数
    function BootstrapModal(element,options,id){
        this.$element = $(element);
        this.model = {
            lg:{
                class:'modal-dialog modal-lg'
            },
            def:{
                class:'modal-dialog'
            },
            sm:{
                class:'modal-dialog modal-sm'
            }
        };
        this.config = $.extend({}, {
            title:'通知',
            model:'def',
            close:true,
            body:'请设置内容',
            footer:true,
            id: id,
            footerButton:[
                {text:"取消",class:"btn btn-default",id:'off'},
                {text:"提交",class:"btn btn-primary",id:'put',click:function () {
                        alert('提交成功')
                    }},
            ]
        },options || {});
        this.$modal = $('<div />',{'class':'modal fade','style':'display: none;',
            'tabindex':'-1','role':'dialog','aria-labelledby':'Label'
        }).attr('id',this.config.id);
        this.$modal_dialog = $('<div />',{'class':this.model[this.config.model].class,'role':'document'});
        this.$modal_content = $('<div />',{'class':'modal-content'});
        this.$modal_header = $('<div />',{'class':'modal-header modal-primary'});
        this.$modal_title = $('<h4 />',{'class':'modal-title','text':this.config.title});
        this.$modal_body = $('<div />',{'class':'modal-body'});
        this.$modal_footer = $('<div />',{'class':'modal-footer'});
        this.init();
    }

    function getId(id = '') {
        var i = id + "_" + (new Date()).getTime()+parseInt(Math.random()*100000);
        if($("#" + i).length > 0){return getId();}else{return i;}
    }

    BootstrapModal.prototype = {
        init:function () {
            let id = this.config.id;
            //右上角删除
            if (this.config.close) {
                this.$modal_header.prepend(
                    $.btn({
                        type : 'button',
                        class: 'close',
                        text : $('<span />',{'aria-hidden':'true','text':'×'})
                    }).attr('data-dismiss','modal').attr('aria-label','Close')
                )
            }
            // 模态框内的内容
            this.$modal_body.html(this.config.body);
            this.$modal_content.append(this.$modal_header.append(this.$modal_title)).append(this.$modal_body);
            if (this.config.footerButton && this.config.footerButton instanceof Array) {
                for (let i = 0 ; i < this.config.footerButton.length; i++) {
                    let opt = this.config.footerButton[i];
                    let isClick = !!opt.click;
                    opt.click = function () {
                        if (isClick) {
                            opt.click;
                            $('#'+id).modal('hide');
                        }else {
                            $('#'+id).modal('hide');
                        }
                    };
                    this.$modal_footer.append($.btn(opt))
                }
            }
            if (this.config.footer) {
                this.$modal_footer.addClass('show')
            }else {
                this.$modal_footer.addClass('hide')
            }
            this.$modal_content.append(this.$modal_footer);
            this.$modal.append(this.$modal_dialog.append(this.$modal_content));
            this.$element.append(this.$modal)
        },
        show:function () {
            $('#'+this.config.id).modal('show');
        },
        id:function () {
            return this.config.id;
        },
        hide:function () {
            $('#'+this.config.id).modal('hide');
        },
        title:function (val) {
            if (val) {
                this.$modal_title.text(val);
                return val;
            }
            return this.$modal_title.text();
        },
        body:function (val) {
            if (val) {
                this.$modal_body.html(val);
                return val;
            }
            return this.$modal_body.html()
        },
        showFooter:function (bool) {
            if ( $.type(bool) === 'boolean') {

                if (this.config.footer) {
                    if (!bool) {
                        this.$modal_footer.addClass('hide').removeClass('show');
                    }
                }else {
                    if (bool) {
                        this.$modal_footer.addClass('show').removeClass('hide');
                    }
                }

                this.config.footer = bool
            }
        },
        footer:function (val) {
            if (val) {
                this.$modal_footer.html(val);
                return val;
            }
            return this.$modal_footer.html();
        }
    };

    // 添加到jQuery对象中
    $.fn.bootstrapModal = function(options,para){

         return this.each(function() {
            var $this   = $(this),
                bootstrapModal = $this.data('bootstrapModal');
            //防止多次初始化
            if (!bootstrapModal) {
                var id = getId('bootstrapModal');
                bootstrapModal = new BootstrapModal(this,options,id);
                $this.data('bootstrapModal', bootstrapModal);
            }

            // 如果是字符串则调用方法
            if($.type(options) === 'string') {
                bootstrapModal[options](para);
            }
         });
    }
})(jQuery);

编写步骤:
1、 添加到jQuery对象中
2、 设置返回值,使其可以使用链式命令
3、 使用$.data()记录初始化对象,防止多次初始化
4、 设置可以使用传参string就可以调用内部方法

// 添加到jQuery对象中
    $.fn.bootstrapModal = function(options,para){
          
         return this.each(function() {
            var $this   = $(this),
                bootstrapModal = $this.data('bootstrapModal');
            //防止多次初始化
            if (!bootstrapModal) {
                var id = getId('bootstrapModal');
                bootstrapModal = new BootstrapModal(this,options,id);
                $this.data('bootstrapModal', bootstrapModal);
            }

            // 如果是字符串则调用方法
            if($.type(options) === 'string') {
                bootstrapModal[options](para);
            }
         });
    }
  1. 定义构造函数,设置默认参数,将调用时传递的参数与默认参数合并
  2. 创建自定义方法
BootstrapModal.prototype = {
  init:····,
  show:····,
······
}
使用方法

1、新建容器,用于承载模态框

<div id="importModal"></div>

2、在js中初始化模态框

    $('#importModal').bootstrapModal({
        title:'导入',
        footer:true,
        body:function () {
            return [
                '<form id="add_commodity_form" method="post" enctype="multipart/form-data">',
                '<div class="form-group" style="width:99%">',
                '<input id="import_postman" name="file" type="file" class="file">',
                '</div>',
                '</form>'
            ].join('')
        },
        footerButton:[
            {text:"取消",class:"btn btn-default",id:'off'},
        ]
    });

3、手动调用模态框的显示

    //导入按钮,打开模态框
    $('#btn_import').on('click',function () {
        $('#importModal').bootstrapModal('show')
    });
效果:
其他参数和方法:
  • title:模态框名称
  • model:模态框大小,可选'lg'(大),'def'(默认),'sm'(小)
this.model = {
            lg:{
                class:'modal-dialog modal-lg'
            },
            def:{
                class:'modal-dialog'
            },
            sm:{
                class:'modal-dialog modal-sm'
            }
        };
  • close:是否显示右上角关闭按钮,truefalse
  • body:模态框显示的内容,可以是 string 或 jQuery对象
  • footer:是否显示底部栏,truefalse
  • id:自定义ID,不设置则根据时间生成ID
  • init:初始化方法,生成模态框添加到容器
  • show:打开模态框
  • hide:关闭模态框
  • id:获取模态框ID
  • 'title':获取或设置标题
//获取 title
$('#importModal').bootstrapModal('title')
//设置 title
$('#importModal').bootstrapModal('title','通知')
  • body:获取或设置body
//获取 body
$('#importModal').bootstrapModal('body')
//设置 body
$('#importModal').bootstrapModal('body',function () {
            return '<h2>这是模态框展示的内容!</h2>'
        })
  • showFooter:是否展示底部栏,truefalse
  • footer:获取或设置底部栏footer
//获取 footer
$('#importModal').bootstrapModal('footer')
//设置 footer
$('#importModal').bootstrapModal('footer',function () {
            return '<button type="button" class="btn btn-primary">确认</button>'
        })

上述方法也可以通过下列方式调用:

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