第二期:JQ插件编写入门(2)

第二期:JQ编写入门(2)

在看过我们上期的技术文章之后,大家应该知道关于JQ插件的大概形式了。如果大家还没有看过我的上一期文章,可以点下面链接
第一期:JQ插件编写入门(1)

JQ插件内部的形式


; (function ($, window, document, undefined) {

    /*这里定义的是私有变量,外部是访问不到的*/
    var pluginName = 'yourPluginName',

        defaults = {

            properties: 'name'

        };

    /*这里定义的是私有函数,供内部调用*/
    function Plugin(element, options) {

        this.element = element;

        this.defaults = $.extend({}, defaults, options);

        this._defaults = defaults;

        this._name = pluginName;

        this.init();

    }

    Plugin.prototype={

        init:function(){

            //code

        },

        otherFunc:function(){

            //code

        }

    };

    /*这里使用了$.fn方法来拓展插件函数,当然也可以使用$.extend(),或者widget factory来达到相同的效果*/
    $.fn.pluginName = function (options) {

        return this.each(function () {

            if (!$(this).data('plugin_' + pluginName)) {

                $(this).data('plugin_' + pluginName, new Plugin(this, options));

            }

        });

    };

})(jQuery, window, document);

函数局部分析

  • 私有变量

 /*这里定义的是私有变量,外部是访问不到的*/
    var pluginName = 'yourPluginName',

        defaults = {

            title: 'title',
            
            msg: '01'

        };

这里的写法,大家可以学习一下。首先我们,只用了一次Var变量声明,这样的好处是,不需要多次进行声明,每个变量定义后,用逗号隔开,最后再以一个分号结尾。其中我们把插件名字pluginName存放在一个变量里面,这样的好处是,我们浏览这个函数的开头,就直接知道这个插件的调用函数名字,而不需要拉到底部的$.fn.pluginName去查看。虽然直接在那儿命名一点错也没有。但是大家要知道,往往我们开发,是需要接手别人的项目,那么当一个插件,写了几百行的代码,如果没有清晰的结构,当别人接手我们项目维护时候,会很耗精力。

然后我们又声明了一个私有变量defaults,这个变量的作用是用来设置我们插件的默认值。为什么这个地方要使用对象来存储我们的默认参数。我们都遇到过一个情况:

function Example(num,string){
    
}

我们常用的传参是一个个往里面传,那么这个时候我们是要注意参数的顺序的,当我们参数很多时候,我们不得不头疼地记住每一个参数的顺序:

function Example(num,string,obj,date,reg){

}
var ex=new Example(num, , , ,reg);

这样子穿参数,就很不方便。所以我们就把参数放到一个对象里面,这样子,我们又可以不用注意参数的顺序,又可以让代码结构更加清晰。我们传参数,就直接写对象的变量名字就好了。

var data={
    num:'',
    string:'',
    obj:'',
    date:'',
    reg:''
}

function Example(data){
    //
}
  • 私有方法

    /*这里定义的是私有函数,供内部调用*/
    function Plugin(element, options) {

        this.element = element;

        this.defaults = $.extend({}, defaults, options);

        this._defaults = defaults;

        this._name = pluginName;

        this.init();

    }

    Plugin.prototype={

        init:function(){

            //code

        },

        otherFunc:function(){

            //code

        }

    };
    
    /*插件代码后段的实例化
    *组合起来看
    * new Plugin(this, options)
    */
    

这里我们用了设计模式,具体关于设计模式我们就不展开去讲。首先我们定义了一个叫Plugin的function,我们在里面用this定义静态变量和方法。

  this.defaults = $.extend({}, defaults, options);

这段代码的意思的是,把传入的参数(就是用户的自定义参数)与我们的默认值(默认参数值)合并到一个对象里面,同时不会修改defaults和options的值。

$.extend(defaults,options)

这样子使用,那么我们options的参数会合并到defaults里面,defaults的默认值就被修改了。但很多时候,我们不希望defaults被修改,所以才用第一种方法。

$.extend(true/false,{},defaults,options)

这个方法的第一个参数是可选的,true代表深克隆,false代表浅克隆,就是true的时候,会递归到数组或者对象深处去合并。通常这个方法用在数组或者对象上,如果只是一般的数据类型,我们有一种很简单的方法实现默认值和自定义值的选择。

var newString = string || '';

var newNum = num ? num : 123;

当我们不需要处理数组或者对象时候,我们就可以用上面两种写法,第一种是有字符串string时候取string,没有则取字符串为空;第二种是有数字num时候取num,没有则取一个默认值数字123.

this.init();

初始化原型方法,当我们实例化这个函数时候,原型函数就执行

Plugin.prototype = {

    init: function () {
        //
    },

    otherFuc: function () {
        //
    }

}

这里我们把函数的方法写到原型里面,当我们实例化的时候,就不需要每次new都把方法都复制一遍。所以,每个Plugin的实例,用的方法都是调用原型里面的,这样可以较好地提升性能。

  • JQ插件拓展方法

    /*这里使用了$.fn方法来拓展插件函数,当然也可以使用$.extend(),或者widget factory来达到相同的效果*/
    $.fn.pluginName = function (options) {

        return this.each(function () {

            if (!$(this).data('plugin_' + pluginName)) {

                $(this).data('plugin_' + pluginName, new Plugin(this, options));

            }

        });

    };

终于到了我们插件拓展的写法了。当我们去看jq源代码的时候,其实:

$.fn = $.prototype;

其实我们这种写法就是在jQuery的原型去拓展一个方法。所以我们在平时使用的时候,就可以用$.pluginName的形式去调用方法。

return ...

为什么这里要return呢,因为当我们返回这个方法,我们可以对它链式调用。例如,$.pluginName1().pluginName2();

return this.each(function(){
    //
});

这里的this,指的是$。在$.fn里面,this是指向jQuery对象。但是在this.each(function(){})里的this,指的是function的每层循环的上下文,如果要用jQuery对象,那么就要用$

return this.each(function () {

    if (!$(this).data('plugin_' + pluginName)) {

        $(this).data('plugin_' + pluginName, new Plugin(this, options));

    }

});

在这个函数里面,我们用if先判断有没有这个插件方法,如果没有,我们就new一个实例,然后数据存储到这个插件里面。在这里我们用到$.data()方法。这个方法简单点说,就是数据缓存到某个元素上面。当我们不带参数的时候,我们就是读取;带参数,就是键值对的设置。

<p></p>

$("p").data(); //undefined
$("p").data("a","hello"); //a=="hello"
$("p").data("b",{first:1,second:"abc"}); 
$("p").data("b").first; //1

用法大概类似如此。

这期介绍了插件的写法,那么下期,和大家分享一下自己写的几个插件实例。

    原文作者:thattoti
    原文地址: https://segmentfault.com/a/1190000008725437
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞