javascript - 事件监听器在某些上下文中无法附加或删除

标签 javascript jquery dynamic web-applications event-handling

我创建了一个脚本,默认将事件监听器附加到图片集合。单击元素时,监听器会交换另一个事件,该事件会更改图像源并将元素的 id 推送到数组,如果单击交换的图像,则情况会相反(源会变回原样,并且图像中的最后一个元素会发生变化)。数组被删除)。有一个按钮可以通过设置默认源并重置事件监听器来“清除”所有图像,但它不能可靠地触发,有时会延迟触发,导致仅收集一系列中的最后一个元素。

TL;DR:一个事件在没有明显原因的情况下非常不可靠地触发,我很想知道为什么会发生这种情况以及我应该如何解决它。下面提供了 JSFiddle 和已发布的版本。

我已上传当前版本here ,您可以通过选择多个表,按“取消”,然后再次选择这些按钮来触发错误。通常错误会在第二次或第三次通过时开始。

我还有一个fiddle .

布局在台式机和笔记本电脑上会有点古怪,因为它是为手机屏幕设计的,但您将能够看到问题并检查代码,因此这应该不是问题。

代码块:

取消设置所有选定的表:

    function tableClear() {

        //alert(document.getElementsByClassName('eatPlace')[tableResEnum].src);
        //numResTables = document.getElementsByClassName('eatPlace').src.length;

        tableArrayLength = tableArray.length - 1;

        for (tableResEnum = 0; tableResEnum <= tableArrayLength; tableResEnum += 1) {

            tableSrces = tableArray[tableResEnum].src;

            //alert(tableSrcTapped);

            if (tableSrces === tableSrcTapped) {
                tableArray[tableResEnum].removeEventListener('click', tableUntap);
                tableArray[tableResEnum].addEventListener('click', tableTap);
                tableArray[tableResEnum].src = window.location + 'resources/tableBase.svg';
            } /*else if () {

            }*/
        }

        resTableArray.splice(0, resTableArray.length);
    }

设置/取消设置特定表:

    tableUntap = function () {
        $(this).unbind('click', tableUntap);
        $(this).bind('click', tableTap);
        this.setAttribute('src', 'resources/tableBase.svg');
        resTableArray.shift(this);
    };

    tableTap = function () {
        $(this).unbind('click', tableTap);
        $(this).bind('click', tableUntap);
        this.setAttribute('src', 'resources/tableTapped.svg');
        resTableArray.push($(this).attr('id'));
    };

将“eatPlace”类中的元素转换为数组:

        $('.eatPlace').bind('click', tableTap);

    tableList = document.getElementsByClassName('eatPlace');

    tableArray = Array.prototype.slice.call(tableList);

表实例化:

   for (tableEnum = 1; tableEnum <= tableNum; tableEnum += 1) {

        tableImg = document.createElement('IMG');
        tableImg.setAttribute('src', 'resources/tableBase.svg');
        tableImg.setAttribute('id', 'table' + tableEnum);
        tableImg.setAttribute('class', 'eatPlace');
        tableImg.setAttribute('width', '15%');
        tableImg.setAttribute('height', '15%');

        $('#tableBox').append(tableImg, tableEnum);

        if (tableEnum % 4 === 0) {
            $('#tableBox').append("\n");
        }

        if (tableEnum === tableNum) {
            $('#tableBox').append("<div id='subbles' class='ajaxButton'>Next</div>");
            $('#tableBox').append("<div id='cazzles' class='ajaxButton'>Cancel</div>");
        }
    }

最佳答案

第一个错误是点击和取消点击表格。

当您将表推送到阵列时,您会推送其 ID。

resTableArray.push($(this).attr('id'));

它将根据用户单击表格的顺序添加元素的 ID。 在取消挖掘时,它总是删除第一个表。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift

resTableArray.shift(this);

因此,当用户单击表 1、2、3 并取消单击 3 时,移位将删除表 1。

让我们通过删除未使用的表来解决这个问题

tableUntap = function () {
    $(this).unbind('click', tableUntap);
    $(this).bind('click', tableTap);
    this.setAttribute('src', 'http://imgur.com/a7J8OJ5.png');
    var elementID = $(this).attr('id');
    var elementIndex = resTableArray.indexOf(elementID);
    resTableArray.splice(elementIndex, 1);
};

所以您在取消点击后丢失了一些表格。

好吧,让我们修复 tableClear,

您有一个包含点击表的数组,但您正在主数组中搜索。

function tableClear() {

    tableLen = resTableArray.length;

    for (var i = 0; i < tableLen; i++) {
        var idString = "#" + resTableArray[i];

        var $element = $(idString);

        $element.unbind('click', tableUntap);
        $element.bind('click', tableTap);
        $element.attr("src", 'http://imgur.com/a7J8OJ5.png');

    }

    resTableArray = [];
}

我只搜索已点击的表,然后取消点击它们并删除处理程序。 fiddle :http://jsfiddle.net/r9ewnxzs/

您的错误是错误地删除了未点击的元素。

关于javascript - 事件监听器在某些上下文中无法附加或删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31245884/

相关文章:

javascript - 将 JavaScript 代码重构为 jQuery 代码

jquery - 如何使用 jQuery 表单插件更新 beforeSubmit 函数中的选项对象

jQuery UI 下拉效果和框大小调整

c# - Delegate.CreateDelegate 与 DynamicMethod 与表达式

javascript - 如何在html和javascript中显示隐藏不确定的圆形进度条

javascript - 尝试让一个新的JS类继承原类的方法

javascript - 如何重新托管 KendoUI 手机模拟器(包括示例)

javascript - Dart 的运算符重载如何转化为 javascript?

bash - awk是否支持动态用户定义变量?

docker - 如何将未知的环境变量列表传递给Dockerfile中的命令