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

时间:2014-10-14 18:38:13

标签: javascript javascript-events

我的目标 - 我想用jQuery做这个:

  1. 从json文件(ajax GET)中检索数据
  2. 使用其中的数据生成链接列表
  3. 当点击其中一个链接时,获取其id(或者可能是另一个属性)的值,使用它来加载相应的数据(来自同一个json文件,也可以通过ajax GET)
  4. 重写此代码以使用回调,我得到了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中?

    非常感谢任何更正,建议和见解。

    SVS

2 个答案:

答案 0 :(得分:0)

您确定var projLink的范围是makeLinks()函数,但更重要的是它也在Ajax回调中,这是一个单独的异步范围。

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

可能的选项包括:

  1. 将所有内容放入request.onreadystatechange() makeLinks()内的{{1}}(不理想)
  2. 调整代码以使用单独的回调函数,并将JSON数据传递给它。你可能不得不捣乱超时&amp;检查以确保数据已定义&amp;在你尝试采取行动之前完成。
  3. 查看有关Ajax响应的this previous question

答案 1 :(得分:0)

在对事件听众进行了进一步阅读后,我发现了我最初的两个问题的答案并解决了我当前的问题,所以如果它对任何人都感兴趣:

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

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

此外,我了解到第三个参数(布尔值)与capture&amp;冒泡,但是我现在不会把自己放在捕获的细微点上。冒泡。我只想说,在我的情况下,我很确定我能够满足我的需求:

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

...(甚至可能没有可选的布尔值,尽管我的理解是包含它的更好的做法(?)

svs,over&amp;进行。