事件侦听器在某些情况下无法附加或删除
Event listener fails to attach or remove in some contexts
我创建了一个脚本,默认情况下将事件侦听器附加到图片集。单击元素时,侦听器换出另一个事件,该事件更改图像源并将元素的 id 推送到数组,如果单击交换的图像则相反(源变回并且最后一个元素在数组被删除)。通过设置默认源和重置事件侦听器,有一个 "clear" 所有图像的按钮,但它不能可靠地触发,有时会延迟触发,导致仅收集系列中的最后一个元素.
TL;DR:一个事件在没有明显原因的情况下非常不可靠地触发,我很想知道为什么会发生这种情况以及我应该如何解决它。下面提供了 JSFiddle 和已发布的版本。
我已经上传了当前版本 here,您可以通过选择多个 table、按 "Cancel",然后再次选择这些按钮来消除错误。通常错误从第二遍或第三遍开始。
我还有一个fiddle。
布局在台式机和笔记本电脑上会有点古怪,因为它是为 phone 屏幕设计的,但您将能够看到问题并检查代码,所以这应该不是问题.
代码块:
取消设置所有选定的 tables:
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);
}
Set/Unset 一个特定的 table:
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'class中的元素转换为数组:
$('.eatPlace').bind('click', tableTap);
tableList = document.getElementsByClassName('eatPlace');
tableArray = Array.prototype.slice.call(tableList);
Table实例化:
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>");
}
}
第一个错误是点击和取消点击 tables。
当您将 Table 推送到数组时,您推送的是它的 ID。
resTableArray.push($(this).attr('id'));
它将添加元素的 id,具体取决于用户单击 table 的顺序。
解锁时总是移除第一个 table。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
resTableArray.shift(this);
因此,当用户单击 tables 1、2、3 并取消单击 3 时,shift 将删除 table 1.
让我们通过移除未开发的 table
来解决这个问题
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);
};
所以你在重置后丢失了一些 tables。
好吧,让我们修复table清除,
您有一个带有点击 table 的数组,但您正在主数组中搜索。
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 = [];
}
我只搜索已点击的 tables,然后只需重置它们并删除处理程序。
fiddle: http://jsfiddle.net/r9ewnxzs/
你的错误是错误地移除了未点击的元素。
我创建了一个脚本,默认情况下将事件侦听器附加到图片集。单击元素时,侦听器换出另一个事件,该事件更改图像源并将元素的 id 推送到数组,如果单击交换的图像则相反(源变回并且最后一个元素在数组被删除)。通过设置默认源和重置事件侦听器,有一个 "clear" 所有图像的按钮,但它不能可靠地触发,有时会延迟触发,导致仅收集系列中的最后一个元素.
TL;DR:一个事件在没有明显原因的情况下非常不可靠地触发,我很想知道为什么会发生这种情况以及我应该如何解决它。下面提供了 JSFiddle 和已发布的版本。
我已经上传了当前版本 here,您可以通过选择多个 table、按 "Cancel",然后再次选择这些按钮来消除错误。通常错误从第二遍或第三遍开始。
我还有一个fiddle。
布局在台式机和笔记本电脑上会有点古怪,因为它是为 phone 屏幕设计的,但您将能够看到问题并检查代码,所以这应该不是问题.
代码块:
取消设置所有选定的 tables:
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);
}
Set/Unset 一个特定的 table:
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'class中的元素转换为数组:
$('.eatPlace').bind('click', tableTap);
tableList = document.getElementsByClassName('eatPlace');
tableArray = Array.prototype.slice.call(tableList);
Table实例化:
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>");
}
}
第一个错误是点击和取消点击 tables。
当您将 Table 推送到数组时,您推送的是它的 ID。
resTableArray.push($(this).attr('id'));
它将添加元素的 id,具体取决于用户单击 table 的顺序。 解锁时总是移除第一个 table。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
resTableArray.shift(this);
因此,当用户单击 tables 1、2、3 并取消单击 3 时,shift 将删除 table 1.
让我们通过移除未开发的 table
来解决这个问题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);
};
所以你在重置后丢失了一些 tables。
好吧,让我们修复table清除,
您有一个带有点击 table 的数组,但您正在主数组中搜索。
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 = [];
}
我只搜索已点击的 tables,然后只需重置它们并删除处理程序。 fiddle: http://jsfiddle.net/r9ewnxzs/
你的错误是错误地移除了未点击的元素。