jQuery点击事件触发两次

4
我正在开发一个内容覆盖脚本,但是我遇到了问题。似乎我的关闭事件会触发两次,但第一次(或第二次,取决于你单击哪个打开链接)返回“未定义”。您可以在JSFiddle上找到一个简化的工作示例:http://jsfiddle.net/UhSLy/2/。如果您单击1. Click,然后再单击2. Click,它首先弹出undefined,然后是Dummy。当我删除一个打开链接时,一切正常。但是我必须有多个链接,因为它们打开不同的覆盖层。什么原因导致这个问题,如何避免它?编辑:以下是来自JSFiddle的代码:
;(function ($, window, document, undefined) {

"use strict";

var pluginName = 'contentOverlay',
    defaults = {
        property:   'value'
    };

function Plugin(element, options) {
    this.element = element;
    this.$element = $(element);

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

    this.init();
}

Plugin.prototype = {

    /**
     * Init
     */
    init: function () {
        var self = this;

        // Bind opening method
        this.$element.click(function() {
            self.open();
        });

        // Bind closing method
        $('#close').click(function() {
            self.close();
        });
    },

    /**
     * Open
     */
    open: function () {
        this.overlay = 'Dummy';
    },

    /**
     * Close
     */
    close: function () {
        alert(this.overlay); // <==== PROBLEM: fires twice. returns 'undefined' once
    },

};

$.fn[pluginName] = function (options) {
    return this.each(function () {
        if (!$.data(this, 'plugin_' + pluginName)) {
            $.data(this, 'plugin_' + pluginName,
                new Plugin(this, options));
        }
    });
}

$(function () {
    $('.open').contentOverlay();
});

})(jQuery, window, document);


当我运行它时,它会两次警告“Dummy”。 - Wayne
@lwburk:我认为这就是重点。 - Robert Harvey
1
请把你Fiddle上的代码粘贴到这里。我们有一个可爱的代码编辑器,它会感到孤独,如果被忽略的话。 - Robert Harvey
@RobertHarvey - 重点是它会运行两次,是的。这不是我指出的问题。我认为他暗示警报的内容是不同的。 - Wayne
当我在Chrome 20和Firefox 11中运行它时,首先会弹出“undefined”,然后是“Dummy”。 @lwburk 您使用的是哪个浏览器? - John B.
3个回答

3
$('#close').click(function() {
    self.close();
});

您将两个对象的close()方法绑定到关闭处理程序。基本上,当您点击关闭按钮时,它会运行两个函数,一个针对每个叠加对象。因为其中一个叠加对象不存在,它返回了undefined

您可以通过以下方式解决此问题:

close: function () {
    if(this.overlay != undefined){ // Skips over the undefined overlays
        alert(this.overlay);
    }
}

DEMO: http://jsfiddle.net/UhSLy/9/


谢谢,那很有道理。在这种情况下,我认为我的插件设计有缺陷/我选择了错误的插件模式。你会如何解决这个问题?(多个打开链接用于不同的内容叠加,只有一个关闭按钮适用于所有内容。) - John B.
@JohnB。不,插件没有缺陷 :) 请看下面的解释,谢谢大家! - Tats_innit

0

如果我可以建议的话,请看这里:http://jsfiddle.net/PgbfN/25/

我猜你这个if条件是用来检查插件是否初始化的,如果是undefined,那么会运行两次。

为了解决这个问题,我添加了一个isApplied标志,一旦应用了就将标志设置为true。希望演示能帮到你:)

希望对你有所帮助

$.fn[pluginName] = function(options) {
        return this.each(function() {
            alert('me ==> ' + (!$.data(this, 'plugin_' + pluginName)) + " ==== " + $.data(this, 'plugin_' + pluginName));
            if (!isApplied) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));

            }
        });
    }

完整代码

var isApplied = false;

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

    "use strict";

    var pluginName = 'contentOverlay',
        defaults = {
            property: 'value'
        };

    function Plugin(element, options) {
        this.element = element;
        this.$element = $(element);

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

    Plugin.prototype = {

        /**
         * Init
         */
        init: function() {
            var self = this;

            // Bind opening method
            this.$element.click(function() {
                self.open();
            });

            // Bind closing method
            $(document).on('click', '#close', function() {
                alert('Close is clicked');
                //self.close(); //<<== Is called
            });
        },

        /**
         * Open
         */
        open: function() {
            this.overlay = 'Dummy';
        },

        /**
         * Close
         */
        close: function() {
            alert(this.overlay); // <==== PROBLEM: fires twice. returns 'undefined' once
        },

    };

   $.fn[pluginName] = function(options) {
        return this.each(function() {
            alert('me ==> ' + (!$.data(this, 'plugin_' + pluginName)) + " ==== " + $.data(this, 'plugin_' + pluginName));
            if (!isApplied) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));

            }
        });
    }

    $(function() {
        $('.open').contentOverlay();
    });

})(jQuery, window, document);

0

我想到了这个(只有这里有改动)

open: function () {
        this.overlay = 'Dummy';
        this.opened=true;
},

$('#close').click(function() {
    if(self.opened) 
    {
        self.opened=false;
        self.close();
    }    
});

我认为代码可以解释一切。如果实例不存在,close事件将永远不会触发。

演示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接