简体   繁体   English

Javascript在循环中附加事件处理程序

[英]Javascript attaching event handler in loop

I'm using the loop to create array of elements(links) and then attaching them with event handlers(one function for all) and adding to the DOM.我正在使用循环创建元素数组(链接),然后将它们与事件处理程序(一个函数为所有)附加并添加到 DOM。 But event handler react only then I click on the last link.但是事件处理程序只有在我点击最后一个链接时才会做出反应。 Code:代码:

xGetUsers = new XMLHttpRequest();
xGetUsers.open("GET","dialogs.php",true);
xGetUsers.send();
xGetUsers.onreadystatechange = function(){
    if (xGetUsers.readyState==4 && xGetUsers.status==200){
        var jUsers=eval("("+xGetUsers.responseText+")");
        if(jUsers){
            var length = jUsers.length;
            var dialogLink = [];
            for(var i=0; i<length; i++) {
                dialogLink[i] = document.createElement("a");
                dialogLink[i].innerHTML = "Go dialog";
                dialogLink[i].usrn = jUsers[i][0];
                dialogLink[i].userID = parseInt(jUsers[i][3]);
                dialogLink[i].id = i;
                dialogLink[i].onclick = getDialog;
                var userinfo = '<div><p>'+jUsers[i][0];
                if(jUsers[i][1]!=0) userinfo += '('+jUsers[i][1]+')';
                userinfo += '</p><p>'+jUsers[i][2]+'</p></div>';
                main_div.innerHTML += userinfo;
                main_div.appendChild(dialogLink[i]);
                }
            }
        }
        
    }
}

getDialog() function: getDialog() 函数:

function getDialog(){
    enduser_id = this.userID;
    enduser_name = this.usrn;
    main_div.innerHTML = '<form><textarea  id="resz"></textarea><a href="" id="send_button" class="main-button">Send</a></form>';
    xLoadMessages.open("GET","get_messages.php?get_id="+enduser_id,true); 
    xLoadMessages.send();
    field = document.getElementById("resz");
    document.getElementById("send_button").onclick = function(){
        if(field.value!=""){
            var message="id="+enduser_id+"&message="+field.value;
            xSendMessage.open("POST","add_message.php",true);
            xSendMessage.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            xSendMessage.send(message);
        }
        return false;
    }
    setTimeout(setRefresh, 3000);
    return false;
}

It react only on last link.它只对最后一个链接做出反应。 I searched for a long time and tried different ways for adding event handler but nothing helped.我搜索了很长时间并尝试了不同的方法来添加事件处理程序,但没有任何帮助。 Help please(.请帮忙(。

I suspect your problem comes from the fact that you create multiple elements with the same ID and then use document.getElementById() to pick them up.我怀疑您的问题来自这样一个事实:您创建了多个具有相同 ID 的元素,然后使用document.getElementById()来获取它们。 Naturally that won't work, your browser decides to give only the last element with that ID.当然这不起作用,您的浏览器决定只给出具有该 ID 的最后一个元素。

More generally speaking you are in need of some modularity in your code.更一般地说,您的代码需要一些模块化。 You need separate functions that deal with Ajax, with user interface building and with user interaction.您需要处理 Ajax、用户界面构建和用户交互的单独函数。

A very simple implementation of an Ajax interface could look like this: Ajax 接口的一个非常简单的实现可能如下所示:

function http() {}
http.urlEncode = function (data) {
    var keys = typeof data === "object" && data ? Object.keys(data) : [],
        enc = encodeURIComponent,
        result = [], key, val;
    if (keys.length && !Array.isArray(data)) {
        while (keys.length) {
            key = keys.pop();
            val = data[key];
            if (typeof val === "undefined") continue;
            result.push(enc(key) + "=" + enc(val));
        }
        return result.join("&");
    } else if (typeof data !== "undefined") {
        return enc("" + data);
    }
};
http.request = function (success, error) {
    var req = new XMLHttpRequest();
    req.onreadystatechange = function () {
        if (this.readyState !== 4) return;
        if (this.status == 200 && typeof success === "function") success.call(this);
        if (this.status != 200 && typeof error === "function") error.call(this);
    };
    return req;
};
http.get = function (url, data, success, error) {
    var req = http.request(success, error);
    data = http.urlEncode(data);
    req.open("GET", url.replace(/\?.*/, "") + (data ? "?" + data : ""));
    req.send();
};
http.post = function (url, data, success, error) {
    var req = http.request(success, error);
    req.open("POST", url);
    req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    req.send(http.urlEncode(data));
};

Now you have convenient http.get() and http.post() helper functions that accept data and callback parameters.现在您有了方便http.get()http.post()辅助函数来接受数据和回调参数。

Next you need a function that can build HTML elements, a rudimentary one could look like this:接下来,您需要一个可以构建 HTML 元素的函数,一个基本的函数可能如下所示:

function newElem(source, text) {
    var elem;
    if (templ.slice(0, 1) === "<") {
        elem = document.createElement("div");
        elem.innerHTML = source;
        elem = elem.firstChild;
    } else {
        elem = document.createElement(source);
    }
    elem.textContent = text;
    return elem;
}

Based on that you can create a function that builds a user element from what the server returns:基于此,您可以创建一个从服务器返回的内容构建用户元素的函数:

function buildUser(data, getDialogHandler) {
    var user, line1, line2, link;

    user = newElem("div");
    line1 = newElem("p", data[0] + (data[1] ? ' (' + data[1] + ')' : "");
    line2 = newElem("p", data[2]);
    link = newElem("<a>Go dialog</a>");
    link.onclick = function (event) {
        getDialogHandler(parseInt(data[3], 10));
    };
    user.appendChild(line1);
    user.appendChild(line2);
    user.appendChild(link);
    return user;
}

And now you can set up the functions that create your user interface.现在您可以设置创建用户界面的功能。 Note how I completely avoid any global variables or HTML IDs and instead work with DOM object references only.请注意我是如何完全避免使用任何全局变量或 HTML ID 的,而只使用 DOM 对象引用。

http.get("dialogs.php", null, function () {
    var mainDiv = document.getElementById("main_div"),
        users;

    try {
        users = JSON.parse(this.responseText);
        users.forEach(function (data) {
            var user = buildUser(data, getDialog);
            mainDiv.appendChild(user);
        });
    } catch (ex) {
        console.log(ex);
    }
});

function getDialog(userId){
    var mainDiv = document.getElementById("main_div"),
        textArea = newElem("textarea"),
        sendBtn = newElem('<a class="main-button">Send</a>');

    sendBtn.onclick = function () {
        if ( !textArea.value ) return;
        http.post("add_message.php", {
            id: userId,
            message: textArea.value
        }, function () {
            // whatever you want to do on add_message success
        });
        return false;
    };

    mainDiv.innerHTML = "";
    mainDiv.appendChild(textArea);
    mainDiv.appendChild(sendBtn);

    http.get("get_messages.php", {get_id: userId}, function () {
        // whatever you want to do on get_messages success
    });

    // setRefresh is never defined anywhere...
    setTimeout(setRefresh, 3000);
}

Notes / Recommendations注释/建议

  • jQuery implements HTTP handling, event handling, element building and countless other things. jQuery 实现了 HTTP 处理、事件处理、元素构建和无数其他的东西。 You see above that it's not impossible to do all those things without jQuery, but it wouldn't hurt to consider it.您在上面看到,如果没有 jQuery,也不是不可能完成所有这些事情,但考虑它并没有什么坏处。
  • You can greatly improve the process of building dynamic HTML user interfaces with HTML templating engines.您可以极大地改进使用 HTML 模板引擎构建动态 HTML 用户界面的过程。 Consider using (for example) Handlebars (this even works for creating HTML on the server side).考虑使用(例如)Handlebars(这甚至适用于在服务器端创建 HTML)。
  • I'm very sure you want to use JSON.parse() instead of eval() .我非常确定您想使用JSON.parse()而不是eval()
  • The code above is meant as an example to learn from.上面的代码是作为一个例子来学习的。 Don't copy and paste it before you understand it.在你理解之前不要复制粘贴。 That also means I give no guarantees that it has no bugs.这也意味着我不保证它没有错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM