Javascript addEventListener在innerHTML之后不工作
我在空闲时间写一个简单的文本游戏。这叫TARDIS flight(Who医生!),我正在处理主菜单。Javascript addEventListener在innerHTML之后不工作,javascript,html,Javascript,Html,我在空闲时间写一个简单的文本游戏。这叫TARDIS flight(Who医生!),我正在处理主菜单。 因此,在设置主菜单的innerHTML之后,我使用一个函数,addMainMenuListeners,添加所有带有addEventListener的事件侦听器。 一切正常,直到我从其中一个子菜单返回主菜单为止。然后,我发现按钮不再工作。在设置innerHTML之后,我正在调用addMainMenuListeners,但即使我这样做了,我在控制台中这样做了,并且我检查了,也没有任何事件。
因此,在设置主菜单的
innerHTML
之后,我使用一个函数,addMainMenuListeners
,添加所有带有addEventListener
的事件侦听器。
一切正常,直到我从其中一个子菜单返回主菜单为止。然后,我发现按钮不再工作。
在设置
innerHTML
之后,我正在调用addMainMenuListeners
,但即使我这样做了,我在控制台中这样做了,并且我检查了,也没有任何事件。
代码:
在我的主javascript文件中:
function addMainMenuListeners()
{
if($("start")) $("start").addEventListener("click", startGame);
if($("instructions")) $("instructions").addEventListener("click", instructions);
if($("settings")) $("settings").addEventListener("click", settings);
if($("back")) $("back").addEventListener("click", resetMainMenu);
if($("volume")) $("volume").addEventListener("change", function(){saveAndChangeVolume($("volume").value);});
}
function instructions()
{
$("mainmenu").innerHTML = "<h1>Instructions</h1><p>Fly your TARDIS through the time vortex using the console. Make sure that you use the correct materialization codes. Try to keep the time-space coordinates close to the values of the ones given. AND DON'T CREATE PARADOXES, WHATEVER YOU DO!</p><button id='back'>Back</button>";
addMainMenuListeners();
return true;
}
function settings()
{
$("mainmenu").innerHTML = "<h1>Volume</h1><span>1</span><input type='range' id='volume' min='1' max='100' /><span>100</span><br><button id='back'>Back</button>";
addMainMenuListeners();
loadVolume();
return true;
}
function resetMainMenu()
{
$("mainmenu").innerHTML = "<h1>TARDIS Flight</h1><button id='start'>Start!</button><button id='instructions'>Instructions</button><button id='settings'>Settings</button>";
addMainMenuListeners();
return true;
}
函数addMainMenuListeners()
{
如果($(“开始”)$(“开始”).addEventListener(“单击”,开始名称);
如果($(“说明”)$(“说明”)。添加了EventListener(“单击”,说明);
如果($(“设置”)$(“设置”).addEventListener(“单击”,设置);
如果($(“返回”)$(“返回”).addEventListener(“单击”,重置主菜单);
if($((“卷”)$(“卷”).addEventListener(“更改”,function(){saveAndChangeVolume($(“卷”).value);});
}
功能指令()
{
$(“mainmenu”).innerHTML=“Instructions使用控制台让您的TARDIS穿越时间漩涡。确保使用正确的物化代码。尽量使时空坐标接近给定的值。无论您做什么,都不要制造矛盾!返回”;
addMainMenuListeners();
返回true;
}
函数设置()
{
$(“主菜单”).innerHTML=“Volume1100
返回”;
addMainMenuListeners();
loadVolume();
返回true;
}
函数resetMainMenu()
{
$(“主菜单”).innerHTML=“TARDIS FlightStart!指令设置”;
addMainMenuListeners();
返回true;
}
在我的HTML文件中:
<div id="mainmenu">
<h1>TARDIS Flight</h1>
<button id="start">Start!</button>
<button id="instructions">Instructions</button>
<button id="settings">Settings</button>
</div>
塔迪斯飞行
开始
说明书
设置
如果你需要任何澄清,尽管问。
编辑:显然,没有人明白我的意思。在执行
innerHTML
之后,我正在读取事件侦听器,您可以从代码中看到这一点。我根本看不到添加的事件,函数正在启动,但没有添加事件。
另外,我正在使用一个自定义的
$
函数,只是一个返回文档.getElementById(id)
类函数。检查您的$()
是否使用任何缓存。如果缓存对元素的旧引用,则当设置innerHTML
时,$(“id”)
将返回对无效引用的引用
[edit]这些引用更有可能有效,即使它们在HTML DOM中不再可见。因此,修改分离的元素是可行的,但没有任何好处,因为它们是从DOM分离的。禁用
$
函数上的缓存是可行的。它引用的是一个被破坏的HTML元素,这就是它不起作用的原因。另外,setTimeout
s在innerHTML
没有及时执行的情况下有助于提高可靠性。抓住了主要问题:您的自定义$函数(用来替换document.getElementById)使用了缓存机制
经过一些测试(出于个人好奇),结果表明,只要您对某个元素有一些引用,即使在elm.parentNode.removeChild
或完整的elm.parentNode.innerHTML
重写(至少在FF中)之后,该元素仍然是可访问的
换句话说:事件每次都被添加到错误的/旧的/以前的元素,而不是新的元素。否则也会出现错误,即元素不存在,因此没有addEventListener
方法
请参阅此原始测试小提琴以获取证据:
我玩弄了一个$函数(因为你还没有发布你的函数),并给它一个“刷新”标志,以配合可选的缓存机制:
var $=function(/*cache_enabled*/c){ // getElementById with optional caching & refresh
return c ?( c={}, function(s,r){return (!r && c[s]) || (c[s]=document.getElementById(s));}
):( function(s){return document.getElementById(s);} );
}(true); // or nothing or 0 etc to disable the cache
注意:动态创建的函数速度较慢(出于某些原因),因此它有两个函数,以便浏览器可以优化运行它们(另一个应该由垃圾收集器清除)
要请求刷新,只需添加一个计算结果为true的标志作为第二个参数,如:$('elm_id',1)
然后,我稍微修改了addMainMenuListeners
函数,首先测试是否存在新的getElementById,然后通过新更新的缓存引用添加eventListener(因此,基本上我没有改变例程流中的任何内容)
格式化以强调更改的内容及其工作方式
最后,将上述2个函数和其他函数/html放入这个提琴中,得到了一个工作结果:注意:我必须替换一个伪函数
startGame
,否则会出现致命错误。缺少的音量功能并不重要
我想指出的是,这不是真正的方式去与您的界面,将有很多工作,你可以节省自己和浏览器。您可能希望查看div(包含html的子部分)并切换它们,以便只有一个可见。像标签。(谷歌查询提示)
Sukima仍然值得称赞(“这一点的力量很强大”),但我觉得分享你的问题的正确解释(有证据)是一个好主意,不要浪费已经完成的工作(出于好奇)
希望这有帮助 我制作了自己的
$
函数。它只是一个返回文档。getElementById(id)
函数。对不起,我没有澄清。伙计们,OP没有使用jQuery。它看起来不像jQuery。OP在上面确认它不是jQuery。如果是jQuery,它根本就不起作用。@Atutouato如果我是你,我会有多个div,其中包含我的TARDIS飞行的“阶段”,并在单击时显示/隐藏这些div,而不是使用。innerHTML
,它正在破坏你的事件
function addMainMenuListeners(){
$( 'start' , 1) && $( 'start' ).addEventListener('click', startGame);
$('instructions', 1) && $('instructions').addEventListener('click', instructions);
$( 'settings' , 1) && $( 'settings' ).addEventListener('click', settings);
$( 'back' , 1) && $( 'back' ).addEventListener('click', resetMainMenu);
$( 'volume' , 1) && $( 'volume' ).addEventListener('change', function(){
saveAndChangeVolume($('volume').value);
});
}