jquery插件最佳结构和阻止方法调用未初始化的对象

时间:2012-11-30 09:46:12

标签: javascript jquery function plugins init

你在这里看到的是我从插件开始的方式:

(function($){
    var methods = {
        init: function(){
            $this = this;
            alert('init '+$this.attr('id'));
        }
        ,
        show_id: function(){
            alert($this.attr('id'));
        }
    };

    var $this;
    // other vars

    $.fn.my_plug = function(method){
        var args = arguments;
        var $this = this;
        return this.each(function(){
            if (methods[method]){
                return methods[method].apply($this, Array.prototype.slice.call(args, 1));
            } else if (typeof method === 'object' || !method){
                return methods.init.apply($this, Array.prototype.slice.call(args, 0));
            } else {
                $.error('Method '+method+' does not exist!');
            }  
        });
    };
})(jQuery);

var a = true;

if (a) $('#object').my_plug(); // alerts "init object"

$('#object').my_plug('show_id'); // alerts "object"

var b = false;

if (b) $('#object_b').my_plug(); // does nothing

$('#object_b').my_plug('show_id'); // calls "show_id"-method … but $this is not defined. It should NOT call because this object is not initialized !!!

在底部你可以看到我如何调用插件方法。

第一个问题:是否有更简洁的方法来获取方法中的“this”/对象? 我认为首先在插件外部定义var,然后在插件内部然后在init-function内部是非常不酷的。有更干净的方法吗?

正如您在底部所看到的:如果if语句为真,我只想调用插件。如果它是真的比它调用init。然后我调用一个插件的方法,它也可以正常工作,因为之前定义/初始化了“$ this”。 但是如果if-statment不是真的并且没有调用插件的“init”方法...我认为可以调用插件的方法是不合逻辑的。

所以这就是问题#2:如果以前没有初始化对象,我如何防止调用方法? 如果我调用$('#object_b').my_plug('show_id');它不应该做任何事情,因为我们没有初始化插件。它应该仅在插件初始化时才可用,或者更确切地说,如果定义了“$ this”。

您怎么看?

2 个答案:

答案 0 :(得分:1)

对于第一个问题,您不需要在插件外声明$ this变量。当您使用this范围调用方法时。您的方法中将提供this。而你能做的就像是

    var methods = {
    init: function(){
        var $this = $(this);     //local to this function
        alert('init '+$this.attr('id'));
    }
    ,
    show_id: function(){
        var $this = $(this);
        alert($this.attr('id'));
    }
};

对于第二个问题,您可以在第一次调用插件时将数据附加到dom对象。如果插件已在此对象上初始化,则可以检查后续调用。

    $.fn.my_plug = function(method){
    var args = arguments;
    return this.each(function() {
        var $this = $(this),
            data = $this.data('your-plugin-inited'); //e.g.

        if (!data) {    //if no data is attached you can call init
            data = $this.data('your-plugin-inited', 1);
            return methods.init.apply($this, Array.prototype.slice.call(args, 0));
        }

        if (methods[method]){
            return methods[method].apply($this, Array.prototype.slice.call(args, 1));
        } else {
            $.error('Method '+method+' does not exist!');
        }  
    });
  }

查看小提琴http://jsfiddle.net/tqvjt/6/

我建议使用jQuery插件模式来更深入地了解插件创作。 http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns

答案 1 :(得分:0)

这就是我想要的(对所有人来说):

(function($){
    var methods = {
        init: function(){
            alert('init '+ this.attr('id'));
            //this.my_plug('show_id'); //call from inside the plugin
        }
        ,
        show_id: function(){
            alert(this.attr('id'));
        }
    };

    $.fn.my_plug = function(method){
        var args = arguments;
        var init = 'init-my_plug';
        return this.each(function() {
            var is_init = $(this).data(init);
            if (methods[method] && is_init){
                return methods[method].apply($(this), Array.prototype.slice.call(args, 1));
            } else if (!is_init && (typeof method === 'object' || !method)){
                $(this).data(init, true);
                return methods.init.apply($(this), Array.prototype.slice.call(args, 0));
            }
        });
    };
})(jQuery);

var a = true; // if a is set to false nothing happens

if (a) $('div').my_plug();
$('div').my_plug('show_id');
$('#div3').my_plug('show_id'); // also works on only one of the divs​​​​​​​​​​

试一试:jsfiddle

做了一些改变:

  • 数据值还必须包含插件名称以防止错误 如果其他插件使用相同的技术,则会出现这种情况。
  • 在第二个if语句中添加了“is_init”