javascript 事件处理问题

0h4hbjxa  于 2023-01-01  发布在  Java
关注(0)|答案(3)|浏览(123)

我有一对夫妇,什么可能最终会为这个论坛,关于不显眼的事件处理过于新手的问题。
据我所知,一个正确设置的文档应该如下所示:

<html>
<head>
<title>Title</title>
<script src="jsfile.js" type="text/javascript></script>
</head>
<body>

//Body content, like some form elements in my case

</body>
</html>

Jsfile.js看起来像这样:

function a() {
//code;
}
function b()...

window.addEventListener('load', a, false);
document.getElementById("id").addEventListener('click', b, false);
document.myForm.typeSel.addEventListener('change', c, false);

//or to use better browser-compatible code...

function addEvent(obj,evt,fn) {
 if (obj.addEventListener)
   obj.addEventListener(evt,fn,false);
 else if (obj.attachEvent)
   obj.attachEvent('on'+evt,fn);
}
addEvent(window, 'load', a);
addEvent(document.getElementById('id'), 'click', b);
addEvent(document.myForm.typeSel, 'change', c);

据我所知,浏览器会在head中加载JavaScript代码,将每个事件处理程序添加到它们各自的元素中。然而......虽然 window 处理程序添加正确,但其他处理程序都没有添加正确。但是如果将 window 处理程序放在 * 一个函数中,(例如)访问元素的getElementById方法工作良好,并且添加了事件处理程序。所以我可以想象地创建一个loadEvents()函数,通过窗口onload调用,它包含了其他文档元素的所有addEvent()函数,我需要这些文档元素的事件处理程序,但是据我所知,我不应该这样做。
此外,如果我将addEvent代码与它所寻址的元素沿着粘贴在主体中,例如:

<input type="checkbox" id="test" />
<script type="text/javascript>
document.getElementById("test").onclick = func;
</script>

...那么它工作得很好。但当然它也违反了删除内联事件处理程序的全部原因!
所以问题是:为了使用*element*.addEventListener('click',func,false)addEvent(*element*,'click',func),甚至*element*.onclick = func-我怎样才能成功地在head中引用脚本文件末尾的元素,而不必将其插入 * 另一个 * 函数?为什么getElementById和其他类似的方法不能在head中的函数之外工作?
或者,是我潜在的理解有缺陷吗?

uz75evzq

uz75evzq1#

<script>放在<head>中曾经是明智之举。但是现在,对于大量 AJAX 页面,<script>越来越多地出现在主体中,尽可能地在下面。这个想法是<script>的加载和解析阻止页面的其余部分加载。这样用户将看到一个空白页面。通过确保正文尽快加载,您可以为用户提供一些可查看的内容。请参阅YAHOO最佳实践以获得有关该问题的详细说明:http://developer.yahoo.com/performance/rules.html
现在,不管这个问题如何,你现在设置的代码都不能工作--至少,当你试图附加处理程序的元素还没有创建的时候是不能工作的。

document.getElementById("id").addEventListener('click', b, false);

如果包含id="id"的元素在body中,你会得到一个运行时错误。现在,如果你把<script>放在body中,在下面,在内容(包括包含id="id"的元素)之后,它就可以工作,因为脚本是在那些元素的html代码被解析并添加到DOM之后执行的。
如果你确实想让脚本出现在头中,你可以这样做,但是你需要同步事件处理程序的添加和页面内容的呈现。你可以通过把它们都添加到文档或窗口加载处理程序中来实现这一点。所以,如果你写:

//cross browser add event handler 
function addEventHandler(obj,evt,fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt,fn,false);
    } else if (obj.attachEvent) {
        obj.attachEvent('on'+evt,fn);
    }
}
addEventHandler(document, 'load', function(){
    //set up all handlers after loading the document
    addEventHandler(document.getElementById('id'), 'click', b);
    addEventHandler(document.myForm.typeSel, 'change', c);
});

它确实有效。

yqkkidmi

yqkkidmi2#

window.addEventListener工作而document.getEle...().addEventListener不工作的原因很简单:window对象在您执行该代码时存在,而带有id="abc"的元素尚未加载。
当你的浏览器下载页面的源代码时,源代码会被尽快解析和执行。所以如果你把script放在head元素中--在源代码的最开始--它甚至会在<div id="abc">...</div>下载之前执行。所以我想现在你知道为什么了

<div id="test">Blah</div>
<script type="text/javascript">document.getElementById("test").style.color = "red";</script>

工作,而这:

<script type="text/javascript">document.getElementById("test").style.color = "red";</script>
<div id="test">Blah</div>

不会。
你可以用很多方法来处理这个问题,最常用的方法是:

  • 将脚本放在文档末尾(</body>之前)
  • 使用事件延迟脚本的执行

第一种方法现在应该很清楚了,但我个人更喜欢最后一种(即使它有点糟糕)。
那么如何处理事件呢?当浏览器最终下载并解析整个源代码时,会执行DOMContentLoaded事件。此事件意味着源代码已准备就绪,您可以使用JavaScript操作DOM。

window.addEventListener("DOMContentLoaded", function() {
    //here you can safely use document.getElementById("...") etc.
}, false);

不幸的是,不是每个浏览器都支持DOMContentLoaded事件,但是一如既往的... Google is the anwser。但是这不是坏消息的结束。正如你所注意到的addEventListener不受IE的支持。嗯...这个浏览器真的让你的生活变得很困难,你必须再破解一件事... Yes... once again - Google。但是它是IE,所以它不是全部。普通浏览器(如Opera或Firefox)支持W3C Event Model,而IE支持its own-所以再一次-谷歌的跨浏览器解决方案。
addEventListener现在看起来似乎是最糟糕的附加事件的方法,但实际上它是最好的方法。它让你可以轻松地为单个元素上的单个事件添加或删除许多侦听器。
附言:我注意到你在考虑使用Load事件来执行你的脚本。不要这样做。Load事件执行得太晚了。你必须等到每个图像或文件都被加载。你应该使用DOMContentLoaded事件。)
编辑:我忘了......当你使用一些像非常流行的jQuery这样的框架时,处理跨浏览器事件模型要容易得多。但是了解浏览器是如何工作的还是很好的。

ffdz8vbo

ffdz8vbo3#

您熟悉jQuery吗?
它是一个javascript库,具有一些非常棒的工具。
例如,如果您希望在页面完全加载并创建所有DOM元素之后立即执行某个js操作(以避免那些恼人的异常),则可以简单地使用ready()方法。
我还看到你想附加click`change事件jQuery`也会处理这个问题:)而且你不必担心所有那些跨浏览器的问题。
看一看jQuery selectors,在尝试获取元素时会使您的工作变得更容易。
好吧,就是这样,给予一试吧,它有一个非常直观的API和一个很好的文档。

相关问题