JavaScript Click Events - 为什么我需要两个addEventListeners?

时间:2012-12-20 20:17:28

标签: javascript click addeventlistener

我正在尽力学习不引人注目的JavaScript。下面的代码是尝试使用从HTML标记内调用的getArrays函数更改现有的练习片段。这是我唯一可以上班的版本。虽然它很好用,但我觉得可能有一些不必要的部分,并且不完全理解为什么我需要最后一行代码(addEventListener的新东西)。我正在使用Mozilla DOM参考示例,并且已经知道如何在jQuery中执行此操作。谢谢!

JavaScript的:

        <script>

        function getArrays() {
            var ddlValArray = new Array();
            var ddlTextArray = new Array();
            var ddl = document.getElementById("ddlFlavors");

            for (i=0; i<ddl.options.length; i++) {
                ddlValArray[i] = ddl.options[i].value;
                ddlTextArray[i] = ddl.options[i].text;
                alert(ddlValArray[i] + ' ' + ddlTextArray[i]);  
            }
        }

        function showArrays() {
            var link = document.getElementById("clickHandler");
            link.addEventListener("click", getArrays, false);   
        }

        document.addEventListener("DOMContentLoaded", showArrays, false);


    </script>

HTML

Select Flavor: 
<select id='ddlFlavors'>
<option value="1">Vanilla</option>
<option value="2">Chocolate</option>
<option value="3">Strawberry</option>
<option value="4">Neopolitan</option>
</select>

<br/><br/>
<a id="clickHandler" href="#">Show Flavors</a>

3 个答案:

答案 0 :(得分:5)

如果正确构建HTML / JS,则不会。

将脚本标记移动到</body>标记之前的正文底部,您不再需要等待DOMContentLoaded事件。它上面的html将在JS执行之前被解析。

这会导致其他警告,但对于您的示例,它会起作用。

<body>
Select Flavor:
<select id='ddlFlavors'>
    <option value="1">Vanilla</option>
    <option value="2">Chocolate</option>
    <option value="3">Strawberry</option>
    <option value="4">Neopolitan</option>
</select>
<br/><br/>
<a id="clickHandler" href="#">Show Flavors</a>
<script>
        function getArrays() {
            var ddlValArray = new Array();
            var ddlTextArray = new Array();
            var ddl = document.getElementById("ddlFlavors");
            for (i=0; i<ddl.options.length; i++) {
                ddlValArray[i] = ddl.options[i].value;
                ddlTextArray[i] = ddl.options[i].text;
                alert(ddlValArray[i] + ' ' + ddlTextArray[i]);  
            }
        }
        function showArrays() {
            var link = document.getElementById("clickHandler");
            link.addEventListener("click", getArrays, false);   
        }
        showArrays();
    </script>
</body>

将脚本放在底部还有许多其他好处。 Read more about them here

有一点需要注意:即使解析了iframe和图像的标签,图像本身也可能无法完成下载,因此您必须等待。此外,iframe内容也可能尚未加载。但是,DOMContentLoaded也不会等待这些。我只是觉得这很好。

答案 1 :(得分:2)

这行代码:document.addEventListener("DOMContentLoaded", showArrays, false);确保您的函数showArrays()在DOM准备好之前不会开始执行。换句话说,函数showArrays()将在加载和解析(X)HTML文档后开始执行。

我建议您将JavaScript代码放在单独的文件中,并使用head部分中的以下HTML代码:<script type="text/javascript" src="yourfilepath.js"></script>。然后,您还可以使用window.onloadonclick个事件代替document.addEventListener()方法。

当你这样做时,你可以将代码放在showArrays函数体外,并删除函数。

例如:

window.onload = function()
{
  var link = document.getElementById("clickHandler");
  link.onclick = getArrays;
}

这被认为是一种更好的做法。

完整示例

script.js档案中:

//This is the beginning of the script...

    function getArrays() {
        var ddlValArray = new Array();
        var ddlTextArray = new Array();
        var ddl = document.getElementById("ddlFlavors");

        for (i=0; i<ddl.options.length; i++) {
            ddlValArray[i] = ddl.options[i].value;
            ddlTextArray[i] = ddl.options[i].text;
            alert(ddlValArray[i] + ' ' + ddlTextArray[i]);  
        }
    }

window.onload = function()
{
  var link = document.getElementById("clickHandler");
  link.onclick = getArrays;
}

在HTML头部内:

<script type="text/javascript" src="script.js"></script>

在大多数情况下,最好将JavaScript与HTML文件分开编写,就像CSS一样。这样,您就可以使HTML代码看起来更整洁,更有条理。

答案 2 :(得分:2)

事件监听器对JS来说是至关重要的。每当用户与您的页面进行交互时,您都需要了解该事件并对其进行响应。
当然,在这个片段中,你的函数假设在DOM中有一个给定id的元素,准备好,设置和等待。可能不是这种情况,这就是为什么你必须等到JS收到OK(DOMReady事件)。

这只是一个非常简单的例子,为什么可能会使用addEventListener。但是当你开始使用Ajax调用时,IMO,事件监听器真的会出现在你的页面中添加新内容:
假设DOM已准备好,但稍后可能会或可能不会请求某些元素(取决于用户输入)。在jQuery中,你会使用这样的东西:

$('#foo').on('click',functionRef);

这个代码运行时不需要 foo 元素,但只要元素添加到dom中,就会根据需要处理点击事件。
在非jQ中,您将使用addEventListener。由于事件模型(有关传播和冒泡的详细信息,请参阅quirksmode),不需要将侦听器直接附加到元素:

document.body.addEventListener('click',function(e)
{
    if ((e.target || e.srcElemet).id === 'foo')
    {
        //function that deals with clicks on foo element
    }
},false);//last param is for bubbling/propagating events

这样,您可以绑定可能异步添加到dom的元素的所有事件,而不必检查每个ajax调用的每个响应...

让我们更进一步:委派。正如您所看到的,在上面的代码段中,我们正在侦听所有点击事件,这些事件发生在 body 中的某个位置。这几乎没有区别:所有点击,因此您不需要为101个元素添加101个不同的点击侦听器,只需添加一个。你需要做的唯一事情就是编写处理程序,使其相应地处理每个元素:

document.body.addEventListener('click',function(e)
{
    e = e || window.event;
    var elem = e.target || e.srcElement;
    switch (true)
    {
        case elem.id === 'foo':
            //either code here or:
            return fooCallback.apply(elem,[e]);//use another function as though it were the handler
        case elem.id.className.match(/\bsomeClass\b/):
            return someClassCallback.apply(elem,[e]);//~= jQuery's $('.someClass').on('click',function);
         case elem.type === 'text':
             //and so on
    }
},false);

相当强大的东西。当然,它还有很多,而且还有缺点(主要是X浏览器的东西),但主要的好处是:

  1. 处理动态添加/删除的元素的事件
  2. 处理所有元素的所有事件的单个事件侦听器可以提高代码效率,有时可以通过提升来提高性能。 here's a nice example of when delegation is in order,遗憾的是,它也显示了X浏览器开发给党带来的痛苦......
相关问题