Javascript Eventlistener不会注册单击
我遇到了一件很奇怪的事情,我真的不知道该怎么解决 我在大学里做一个项目,我们的任务是制作一个游戏来测试用户的智力。每个游戏都有自己的模块 我现在正在处理的一个基本上是在使用Javascript Eventlistener不会注册单击,javascript,settimeout,addeventlistener,Javascript,Settimeout,Addeventlistener,我遇到了一件很奇怪的事情,我真的不知道该怎么解决 我在大学里做一个项目,我们的任务是制作一个游戏来测试用户的智力。每个游戏都有自己的模块 我现在正在处理的一个基本上是在使用window.setTimeout将一组标志翻转过来之前显示一秒钟。这工作绝对不错,过渡和一切看起来都很顺利。在我设置电路板(显示标志)的过程中,我还为每个标志提供了一个eventListener,它会侦听单击,从而在其Y轴上翻转标志 不过,任务的最后一部分是创建并显示标志列表。我正在使用一个名为set\u list的单独函数
window.setTimeout
将一组标志翻转过来之前显示一秒钟。这工作绝对不错,过渡和一切看起来都很顺利。在我设置电路板(显示标志)的过程中,我还为每个标志提供了一个eventListener
,它会侦听单击
,从而在其Y轴上翻转标志
不过,任务的最后一部分是创建并显示标志列表。我正在使用一个名为set\u list
的单独函数,它只是将一个有序列表添加到gameboard的innerHTML中
但每当我添加列表时,eventListener就会中断(即,当单击翻转的标志时,它不会激活)
当点击一个按钮时,游戏本身就开始了。因此,基本上有一个按钮具有自己的eventListener
,需要按下该按钮,gameboard才能启动:
document.getElementById('start').addEventListener('click', function(){
setup_cards();
create_cards();
set_list();
});
这两个功能似乎把事情搞得一团糟:
function create_cards() {
for (i = 0; i < cards_arr.length; i++) {
if (i == 3 || i == 6) {
flag_divs += "</div><div class='row flag-buffer'>"
}
if (flags[cards_arr[i]].name == 'Colombia' || flags[cards_arr[i]].name == 'Chile' || flags[cards_arr[i]].name == 'Japan') {
flag_divs += "<div id='flag_" + i + "' class='flip-container col-xs-2 col-xs-offset-1'>" +
"<div class='front'>" +
"</div>" +
"<div class='back'>" +
specialflag(flags[cards_arr[i]].name) +
"</div>" +
"</div>";
} else {
flag_divs += "<div id='flag_" + i + "' class='flip-container col-xs-2 col-xs-offset-1'>" +
"<div class='front'>" +
"</div>" +
"<div class='back'>" +
"<div id='" + flags[cards_arr[i]].class + "' class='flag'> </div>" +
"</div>" +
"</div>";
}
}
board.innerHTML = '<h3 class="text-center"> Memorize the flags </h3><div class="container-fluid"> <div class="row">' + flag_divs + '</div></div>';
var myNodeList = document.getElementsByClassName('flip-container');
for (var iterator = 0; iterator < myNodeList.length; iterator++) {
var el = document.getElementById(myNodeList["flag_" + iterator].id);
el.id = iterator;
//console.log(el);
el.style.transform = 'rotateY(180deg)';
el.classList.add('flipper');
el.addEventListener('click', function () {
animate(this);
});
var animate = function (sender) {
sender.style.transform = "rotateY(0deg)";
console.log("animating");
sender.style.transform = "rotateY(180deg)";
sender.classList.add('flipper');
};
}
window.setTimeout(() => {
for (var iterator = 0; iterator < myNodeList.length; iterator++) {
var el = document.getElementById(myNodeList[iterator].id);
el.id = iterator;
el.style.transform = 'rotateY(0deg)';
console.log("I'm done!");
}
}, 1000);
}
function set_list() {
console.log("I'm in");
var flag_list = "<ol>";
for (var i = 0; i < cards_arr.length; i++) {
flag_list += "<li>" + flags[cards_arr[i]].name + "</li>";
}
flag_list += "</ol>";
board.innerHTML += flag_list;
console.log(board.innerHTML);
}
函数创建卡片(){
对于(i=0;i{
for(var iterator=0;iterator”+标志[卡片阵列[i]]。名称+””;
}
标志_列表+=“”;
board.innerHTML+=标志列表;
log(board.innerHTML);
}
能否在getElementById()调用后添加一些空测试,例如:
if ( el == null ) {
// Error handler.
} else {
// Your existing code.
}
你的问题是:
board.innerHTML += flag_list;
这样做的目的是要求将board
元素的内容作为HTML字符串,在该字符串的末尾添加一些HTML,然后删除board
的内容,并用解析的字符串替换它们。新创建的开始按钮节点没有附加任何事件侦听器,因此不会发生任何事情
由于许多原因,使用element.innerHTML+=some_html
是一个坏主意,这就是其中之一。最好尽可能避免使用.innerHTML
- 将尽可能多的游戏文本/HTML(在本例中,特别是开始按钮,以及说明文本)放入原始静态HTML,而不是使用JS添加
- 要操纵现有HTML,请使用DOM节点操纵操作,如
和document.createElement
,它们根据DOM树而不是文本工作element.appendChild
相对安全的用法是设置新创建元素的初始内容.innerHTML
innerHTML
后执行addEventListener
。也就是说,将事件侦听器代码从create_cards
中取出,并将其放在set_list()
之后将调用的位置(根据您的喜好,是否在函数中)
另外,通过字符串连接构建HTML,就像您正在做的那样
... + "<div id='" + flags[cards_arr[i]].class + "' class='flag'> </div>" + ...
…+" " + ...
这是非常糟糕的做法,因为——不是在本例中,而是在其他情况下——它会导致XSS安全漏洞。如果插入的字符串包含引用字符,则会发生什么情况。
使用DOM方法(
createTextNode
、setAttribute
或属性等)构造节点是避免XSS风险的一个好方法,因为您不需要确保引用或清除文本。检查您的浏览器控制台是否有任何错误?@NewToJS建议不错,但是是的。我在当地做过几次。但是我不确定小提琴的错误。试着用这个小提琴。是的,很抱歉。我已经设置好了,但一定是挂错了小提琴。容易出错…:/不考虑XSS和安全问题,因为这实际上不在任务范围内,我如何着手解决这个问题?更具体地说,在代码中,