JQuery 插件的编写

jquery的插件机制

为了方便用户创建插件,jquery提供了.extend()和.fn.extend()方法。
.extend(object) ,用于扩展jQuery类本身,也就是用来在jQuery类/命名空间上增加新函数,或者叫静态方法. 例如 jquery内置的 ajax方法都是用.ajax()这样调用的,有点像 “类名.方法名” 静态方法的调用方式。

$.extend({
    minValue: function (a, b) {
        // 比较两个值,返回最小值
        return a < b ? a : b;
    }
});
//调用
var i = 100; j = 101;
var min_value = $.minValue(i, j); // min_value 等于 100
$.extend([deep], target, object1, [objectN]);
用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
参数
    deep:可选。如果设为true,则递归合并。
    target:待修改对象,如果不指定target,则给jQuery命名空间本身进行扩展。
    obj1:待合并到第一个对象的对象
    objectN:可选。待合并到第一个对象的对象。
例:
    var obj1 = { a: false, b: 1, c: "abc" }; 
    var obj2 = { a: true, c: "def" }; 
    $.extend(obj1, obj2);
    // 输出 obj1 = { a: true, b: 1, c: "def" }
套路:
    var opts = $.extend({}, defaluts, options);
    // 用自定义插件参数去覆盖插件的默认参数

$.fn.extend(object)扩展 jQuery 元素集来提供新的方法(通常用来制作插件)。

$.fn = $.prototype = {
   init: function( selector, context ) {.....};
};

原来 .fn =.prototype,也就是jQuery对象的原型。那jQuery.fn.extend()方法就是扩展jQuery对象的原型方法。

自执行的匿名函数/闭包

匿名函数最大的用途是创建闭包(这是JavaScript语言的特性之一),并且还可以构建命名空间,以减少全局变量的使用。

封装JQuery插件

接下来我们一起来写个 监听文本框,动态显示下拉选项 (类似搜索提示)插件

1.定一个闭包区域,防止插件"污染"

//闭包限定命名空间
(function ($) {
    // do something
})(window.jQuery);

2.jQuery.fn.extend(object)扩展jquery 方法,制作插件

//闭包限定命名空间
(function ($) {
    $.fn.extend({
        getAjaxOption:function(options){
            // do something
        }
    });
})(window.jQuery);

3.给插件默认参数,实现 插件的功能
//闭包限定命名空间

(function ($) {
    $.fn.extend({
        getAjaxOption: function (options) {
            var opts = $.extend({}, defaluts, options); // 使用jQuery.extend 覆盖插件默认参数
            // 为body绑定事件,判断当点击别的区块,隐藏下拉选项区块
            $(document).on('click',function(event){
                event = window.event || event; 
                var target = $(event.srcElement || event.target);  
                var is_select = opts.container_class+' *,'+opts.container_class+','+opts.target_class+' *,'+opts.target_class;
                if(!target.is(is_select)){
                    $(opts.container_class).hide();
                }
            })
            return this.each(function () {  // 这里的this 就是 jQuery对象,这里 return 为了支持链式调用
                // 遍历所有选中的dom
                var $this = $(this); // 获取当前dom 的 jQuery对象,这里的this是当前循环的dom
                console.log(opts);  // opts为当前所有的配置项
                // 接下来,在当前dom下生成下拉选项的dom元素
                $this.parent().css('position','relative');
                $this.addClass(opts.target_class.slice(1))
                     .after('<div class="'+opts.container_class.slice(1)+'">'+
                        '<div class="'+opts.container_class.slice(1)+'-box">'+
                            '<div class="'+opts.no_data_class.slice(1)+'">'+opts.no_data_msg+'</div>'+
                        '</div>'+
                     '</div>');
            });
        }
    });
    //默认参数
    var defaluts = {
        container_class:'.container-options',   // 下拉选项容器class
        target_class:'.ajaxOptionThis',         // 当前dom的标识class 
        option_class:'.item',                   // 生成的下拉选项的class
        no_data_class:'.no-data',               // 无数据时对应项的class
        no_data_msg:'未找到相关数据',              // 无数据时对应项显示的文字信息
         ajax_url:'******',                     // 请求的地址
        ajax_type:'get',                        // 请求的类型
        ajax_data:{                             // 请求的额外参数
            city : 'zg',
            page : 1
        },
        ajax_keyword_name:'kw',                 // 请求的关键词的name值,value值固定为当前文本框的值
    };
})(window.jQuery);

5.插件私有方法
有些时候,我们的插件需要一些私有方法,不能被外界访问。

//私有方法,检测用户传进来的参数是否合法
function isValid(options) {
    return !options || (options && typeof options === "object") ? true : false;
}

6.公共方法 给别人来扩展你的插件 或者 返回一些回调api

// 公共方法
// 当点击了选项后的回调函数,$this为当前输入框,that为当前点击的选项,opts为插件的配置项集合
$.fn.getAjaxOption.clickCallback = function ($this,that,opts) {}
// 当ajax返回成功后执行的回调函数,$this为当前输入框,response为后端返回的数据,opts为插件的配置项集合
$.fn.getAjaxOption.successCallback = function ($this,response,opts) {}

完整的插件代码如下:

<style>
.container-options{position:absolute;min-width:100%;left:0;background:#fff;z-index:1;display:none}
.container-options .container-options-box{margin-top:-1px;border:1px solid #ccc;max-height:150px;overflow:auto}
.container-options .item,.container-options .no-data{text-align:center;transition:all .3s;cursor:pointer;line-height:1;padding:8px 0;text-align:center}
.container-options .item:hover{color:#fff;background:#eb6120}
.container-options .no-data{display:none}
</style>
(function ($) {
    $.fn.extend({
        getAjaxOption: function (options) {
            //检测用户传进来的参数是否合法
            if (!isValid(options)) return this;
            var opts = $.extend({}, defaluts, options);
            $(document).on('click',function(event){
                event = window.event || event; 
                var target = $(event.srcElement || event.target);  
                var is_select = opts.container_class+' *,'+opts.container_class+','+opts.target_class+' *,'+opts.target_class;
                if(!target.is(is_select)){
                    $(opts.container_class).hide();
                }
            })
            return this.each(function () { 
                var $this = $(this);
                $this.parent().css('position','relative');
                $this.addClass(opts.target_class.slice(1))
                     .after('<div class="'+opts.container_class.slice(1)+'">'+
                                '<div class="'+opts.container_class.slice(1)+'-box">'+
                                    '<div class="'+opts.no_data_class.slice(1)+'">'+opts.no_data_msg+'</div>'+
                                '</div>'+
                            '</div>');
                // 为当前输入框绑定 事件监听,动态获取值
                $this.on('input',function(){
                    var data = {};
                    data[opts.ajax_keyword_name] = $.trim($this.val());
                    data = $.extend({}, opts.ajax_data, data);
                    if( data[opts.ajax_keyword_name].length <=0 ){ return false; }
                    $.ajax({
                        type:opts.ajax_type,
                        url :opts.ajax_url,
                        data: data,
                        success: function(response){
                            $.fn.getAjaxOption.successCallback($this,response,opts);
                        }
                    });
                })
                // 为下拉选项的每一项绑定click事件
                $(opts.container_class).on('click',opts.option_class,function(){
                    $.fn.getAjaxOption.clickCallback($this,this,opts);
                })
            });

        }
    });
    //默认参数
    var defaluts = {
        // 容器dom
        container_class:'.container-options',
        target_class:'.ajaxOptionThis',
        option_class:'.item',
        no_data_class:'.no-data',
        no_data_msg:'未找到相关数据',
        ajax_url:'*****',
        ajax_type:'get',
        ajax_data:{
            city : 'zg',
            page : 1
        },
        ajax_keyword_name:'kw',
    };
    //公共方法
    $.fn.getAjaxOption.clickCallback = function ($this,that,opts) {
        $this.val($(that).text());
        $(opts.container_class).hide();
    }

    $.fn.getAjaxOption.successCallback = function ($this,response,opts) {
        $(opts.container_class).show().find(opts.option_class).remove();
        if(response.data == "no result"){
            $('.no-data',opts.container_class).show();
        }else{
            $('.no-data',opts.container_class).hide();
            var list = '';
            for (var i=0; i<response.data.list.length; i++){
                list += '<div class="'+opts.option_class.slice(1)+'" data-id="'+response.data.list[i].id+'">'+response.data.list[i].name+'</div>';
            }
            $(opts.container_class+'-box').append(list);
        }
    }
    //私有方法
    function isValid(options) {
        return !options || (options && typeof options === "object") ? true : false;
    }
})(window.jQuery);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容