簡體   English   中英

Javascript在循環中附加事件處理程序

[英]Javascript attaching event handler in loop

我正在使用循環創建元素數組(鏈接),然后將它們與事件處理程序(一個函數為所有)附加並添加到 DOM。 但是事件處理程序只有在我點擊最后一個鏈接時才會做出反應。 代碼:

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(){
    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;
}

它只對最后一個鏈接做出反應。 我搜索了很長時間並嘗試了不同的方法來添加事件處理程序,但沒有任何幫助。 請幫忙(。

我懷疑您的問題來自這樣一個事實:您創建了多個具有相同 ID 的元素,然后使用document.getElementById()來獲取它們。 當然這不起作用,您的瀏覽器決定只給出具有該 ID 的最后一個元素。

更一般地說,您的代碼需要一些模塊化。 您需要處理 Ajax、用戶界面構建和用戶交互的單獨函數。

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));
};

現在您有了方便http.get()http.post()輔助函數來接受數據和回調參數。

接下來,您需要一個可以構建 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;
}

基於此,您可以創建一個從服務器返回的內容構建用戶元素的函數:

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;
}

現在您可以設置創建用戶界面的功能。 請注意我是如何完全避免使用任何全局變量或 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);
}

注釋/建議

  • jQuery 實現了 HTTP 處理、事件處理、元素構建和無數其他的東西。 您在上面看到,如果沒有 jQuery,也不是不可能完成所有這些事情,但考慮它並沒有什么壞處。
  • 您可以極大地改進使用 HTML 模板引擎構建動態 HTML 用戶界面的過程。 考慮使用(例如)Handlebars(這甚至適用於在服務器端創建 HTML)。
  • 我非常確定您想使用JSON.parse()而不是eval()
  • 上面的代碼是作為一個例子來學習的。 在你理解之前不要復制粘貼。 這也意味着我不保證它沒有錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM