1

好吧,这不是我的第一个 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);

附加资源
插件演示
插件文档和完整源代码

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

4

1 回答 1

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"这也方便地删除了事件侦听器。

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

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;
};
于 2013-08-04T15:09:15.150 回答