将事件监听器(在回调函数中)添加到生成的元素中

Adding Event Listeners (in a callback function) to generated elements

本文关键字:添加 元素 监听器 回调 函数 事件      更新时间:2023-09-26

我的目标-我想在没有jQuery:的情况下做到这一点

  1. 从JSON文件中检索数据(ajax GET)
  2. 使用其中的数据生成链接列表
  3. 当点击其中一个链接时,获取其id的值(或者可能是另一个属性),使用它来加载相应的数据(来自同一个JSON文件,也通过ajax get)

在重写了这段代码以使用回调之后,我正在获取JSON数据并创建链接。然而,关于addEventListener的工作方式,我对两件事感到困惑:首先,为什么在for循环中添加事件侦听器时调用showProj函数(到目前为止,只提醒每个链接的id)?其次,为什么链接在点击后没有响应?我认为添加事件侦听器只是使生成的链接可以点击吗?

function ajaxReq() {
    var request = new XMLHttpRequest();
    return request;
}
function getJsonData(makeLinks) { // makeLinks = the callback
    var request = ajaxReq();
    request.open("GET", "/json/projects.json", true);
    request.setRequestHeader("content-type", "application/json");
    request.send(null);
    request.onreadystatechange = function() {
        if (request.readyState === 4) {
            if (request.status === 200) {
                makeLinks(request.responseText);
            }
        }
    } // onreadystatechange
} // getJsonData
getJsonData(makeLinks);
function makeLinks(result) { // result = request.responseText
    var projects = JSON.parse(result);
    var projects = projects["Projects"];
    var projectList = document.getElementById("project-list"); // ul#project-list
    for (var project in projects) {
        var projectId = projects[project].id;
        var listItem = "<li><a class='"project-link'" id='""+projects[project].project+"'" href='"#'">" + projects[project].project + "</a></li>";
        projectList.innerHTML += listItem;
    }
    var projLink = document.getElementsByClassName("project-link");
    for (var i = 0; i < projLink.length; i++) {
        var projId = projLink[i].id;
        projLink[i].addEventListener("click", showProject(projId), false); // ** ?? **
    }
} // makeLinks
function showProject(projId) {
    /*
        function showProject will load data corresponding to the link's id (or another attribute);
        presently there are only alerts until the links are working
    */
    alert("projId is: " + projId);
} // showProject

同样,我最终想要的只是点击.project-link类链接,获取其id(或其他一些属性),然后加载相应的数据,例如(伪代码):

projLink.onclick = function(){
    var projId = this.id;
    showProject(projId);
}

我意识到我可以用这个做到:

$(document).ready(function() {
    $("#project-list").on("click", 'li a', function() {
        var projId = this.id;
        showProject(projId);
    })
})

但我想知道为什么事件监听器一开始就不能工作(也就是说,没有jQuery位)。

最后:在这种情况下,通过全局定义var-projLink来排除范围问题,这样我就不必重新定义它,例如在showProj内部,这会被认为是邪恶的坏做法吗?

非常感谢您的任何更正、建议和见解。

var projLink的作用域是makeLinks()函数,这是正确的,但更重要的是,它也在Ajax回调中,这是一个单独的异步作用域。

当Ajax代码异步运行时,JS的其余部分也会继续运行。因此,如果您调用另一个函数getElementsByClassName("project-link"),很可能还没有,因为Ajax回调还没有完成它的工作。

可能的选项包括:

  1. 将Ajax request.onreadystatechange()中的所有内容都放在makeLinks()中(不理想)
  2. 调整代码以使用单独的回调函数,并将JSON数据传递给它;检查以确保数据被定义&在你尝试采取行动之前先完成

看看前面这个关于Ajax响应的问题。

在进一步阅读了事件监听器之后,我发现了最初两个问题的答案,并解决了当前的问题,因此,如果有人感兴趣:

projLink[i].addEventListener("click", showProject(projId), false);

在上面的语句中调用"showProj"函数是因为i)它(也是)一个回调,如果我理解正确的话,ii)因为提供了一个参数;因此,当for循环中的每个元素都添加了click事件时,就会调用它。显然,如果没有为addEventListener回调提供参数,那么回调函数确实会在单击时调用。[欢迎对此有更多见解]

此外,我了解到第三个参数(布尔值)与capture&冒泡,然而,我现在不会偏离自己的捕获和;起泡。可以说,就我而言,我相当肯定我可以这样满足我的需求:

projLink[i].addEventListener("click", showProject, false);

(甚至可能完全没有可选的布尔值,尽管我的理解是最好将其包括在内(?)

svs,over&出来