第一个jQuery插件 - 如何处理重新初始化的事件?

时间:2013-08-04 14:58:59

标签: javascript jquery jquery-plugins

嗯,这不是我的第一个jQuery插件,但我认为其他人会受益。所以对我来说,它是第一次确保每个可能的应用程序按预期工作。

我的插件处理模态较少的叠加,因此必须侦听一些事件。如果插件被重新初始化,那么旧的听众似乎仍然存在并导致故障。

我的解决方案如下:

var oldSettings = $(_this).data('mlOverlaySettings');
if(oldSettings) {
    $(oldSettings.target).unbind('click.mlOverlay');
    $(document).unbind('click.mlOverlay');
    $(document).unbind('keyup.mlOverlay');
}

对我而言,似乎问题与使用$.data函数保存插件状态以及未正确发布的引用有任何关系。

$(_this).data('mlOverlaySettings', settings);
$(_this).data('mlIsOverlayVisible', false);

其他资源
Plugin Demo
Plugin documentation and full source code

解除旧事件的绑定有点难看。我在这里做错了还是总是需要?

1 个答案:

答案 0 :(得分:1)

您应该在jQuery样板方法中阻止重新初始化:

(function($) {
    var PLUGIN_IDENTIFIER = "my-plugin";

    ...plugin definition etc


    //jQuery boilerplate
    $.fn.myPlugin = function(opts) {
        return this.each(function() {
            var instance = $(this).data(PLUGIN_IDENTIFIER);
            //Prevent reinit on this element
            if (!instance) {
                instance = new MyPlugin(this, opts);
                $(this).data(PLUGIN_IDENTIFIER, instance);
            }
            //Method call
            if (typeof opts === "string") {
                instance[opts].apply(instance, [].slice.call(arguments, 1));
            }
        });
    };
})();

您应始终提供"destroy"方法,以删除它添加的.data和事件侦听器。因此,只有在调用"destroy"之后才能重新初始化,这样可以方便地删除事件监听器。

这是一个非常标准的destroy方法的示例实现:

function MyPlugin(element, opts) {
    this.element = $(element);
    this.opts = $.extend(defaults, $(element).data(), opts);
    //Other instance state
    //absolutely do not use $.data for this, you should only occupy one $.data
    //slot for your plugin for the same reason you only occupy one slot on
    //$.fn
}
MyPlugin.prototype.destroy = function() {
    this.element.removeData(PLUGIN_IDENTIFIER);
    this.element.off(".myplugin"); //Remove all events off the element that belong to the plugin's namespace
    //.remove() any helper elements created by the plugin
    this.element = null;
};