addEventListener 中的 appendChild 在第一次申请后不工作

appendChild within addEventListener not working after first application

我有一个网页,其中有 1 到 N(默认 3 个,最多 7 个)交换 div 个元素——称为“会话”——选择一个后,其他元素应该消失(不被隐藏),即所选会话应取代前一个会话。有一个函数允许用户在 div 之间切换,并且在加载页面时调用该函数:

function generarSteps() {
    var numSteps = 0;
    for (let i = 1; i <= 7; i++) {
        if (document.getElementById("switch_" + i).checked == true) {
            numSteps = i;
            break;
        }
    }

    $('#num_sesiones').html('');

    stepsString = "";
    for (let j = 1; j <= numSteps; j++) {
        stepsString += '' +
            '<div class="uc-step" id="sesion_bubble_' + j + '">' +
            '<div class="uc-step_head">' +
            '<div class="uc-step_line"></div>' +
            '<div class="uc-step_count" onclick="selectSesion(' + j + ')"></div>' +
            '</div>' +
            '<div class="uc-step_info">' +
            '<div class="p-size--sm text-weight--bold">Sesión ' + j + '</div>' +
            '</div>' +
            '</div>';
    }

    $('#num_sesiones').append(stepsString);
    selectSesion(1);
}

selectSesion:(部分,只有导致问题的部分)

function selectSesion(sesion) {
    $('#materiales').empty();

    materialesString = "" +

        '<div class="p-16" style="height: 300px;">' +

        '<div class="row mx-0" style="height: 156px">' +

        '<div class="my-auto" style="width: 25%;">' +
        '<div id="docs_existentes_' + (sesion - 1).toString() + '" class="uc-form-group m-0 py-16">' +
        '<input id="myInput_' + sesion + '" type="text" class="uc-input-style doc_input mr-16" style="max-width: 255px;" placeholder="Seleccione...">' +
        '</div>' +

        '<div id="doc_nuevo_' + (sesion - 1).toString() + '"></div>' +
        '</div>' +
        '<div id="docs_selec_' + (sesion - 1).toString() + '" class="uc-card" style="width: 75%; background-color: #F6F6F6"></div>' +

        '</div>' +

        '</div>';

    $('#materiales').append(materialesString);

    documentosDropdown(sesion - 1);
    documentosSeleccionados(sesion - 1);
}

documentosDropdown:

function documentosDropdown(num_sesion) {
    docs = [];
    for (let j = 0; j < documentos[num_sesion].length; j++) {
        if (documentos[num_sesion][j].SELECCIONADO != 1) {
            docs.push(documentos[num_sesion][j].NOM_ARCHIVO);
        }
    }

    autocomplete(document.getElementById("myInput_" + (num_sesion + 1).toString()), docs, num_sesion);
}

这里是自动完成错误发生的地方:

function autocomplete(inp, arr, num_sesion) {
    var currentFocus;

    // for (var j = 1 ; j <= 7 ; j++) {
    //  $('#myInput_' + j).unbind('click');
    //  $('#myInput_' + j).unbind('input');
    // }

    inp.addEventListener("click", handler, false);
    inp.addEventListener("input", handler, false);

    function handler() {
        alpha;
        beta;
        var i;
        var val = this.value;

        closeAllLists();
        currentFocus = -1;

        alpha = document.createElement("div");
        // document.getElementById("myInput_" + (num_sesion + 1).toString()).parentNode.appendChild(alpha);
        this.parentNode.appendChild(alpha);

        alpha.setAttribute("id", "myInput_" + (num_sesion + 1).toString() + "_autocomplete-list");
        alpha.setAttribute("class", "autocomplete-items mr-16");
        alpha.style.maxHeight = "225px";
        alpha.style.overflowY = "auto";
        alpha.style.top = "61px";

        for (i = 0; i < arr.length; i++) {
            var indexOf = arr[i].toUpperCase().indexOf(val.toUpperCase());

            if (indexOf > -1) {
                beta = document.createElement("div");

                beta.innerHTML = arr[i].substr(0, indexOf) + "<strong>" + arr[i].substr(indexOf, val.length) + "</strong>" + arr[i].substr(val.length + indexOf);
                beta.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
                alpha.appendChild(beta);

                beta.addEventListener("click", function(e) {
                    selectDocumento(this.getElementsByTagName("input")[0].value, num_sesion);
                    inp.value = "";
                    closeAllLists();
                });
            }
        }
    }

    function closeAllLists(elmnt) {
        var x = document.getElementsByClassName("autocomplete-items");
        for (var i = 0; i < x.length; i++) {
            if (elmnt != x[i] && elmnt != inp) {
                x[i].parentNode.removeChild(x[i]);
            }
        }
    }

    document.addEventListener("click", function(e) {
        closeAllLists(e.target);
    });
}

第一次加载页面时,selectSesion(1)(或我在其中放置的任何会话号)加载,当单击输入或在其中写入任何内容时,下拉菜单正常显示.但是,当我单击包含 selectSesion(n) 值的其他元素之一时,单击输入将不再弹出下拉列表,即使每当我在输入元素中写入时它都会出现。

只是为了测试,我在 autocomplete 函数之外声明了 alpha 变量,它表明确实创建了 alpha 并且甚至填充了 beta div 元素,但是它本身永远不会附加到输入元素的父节点,只有当它是第一个 selectSesion(1) 的原始下拉列表或每当我在输入元素中写入时。

我猜这与 javascript 的异步性质有关,但我对 javascript 还很陌生,所以我无法确定需要什么才能拥有该子节点附加到输入的父节点。

简而言之:

我希望它始终附加 div 元素,无论是在输入元素上单击还是输入。很抱歉太长了 post,但在解决手头的问题之前发生了很长的事件。

最坏的情况,我想知道是否有一种方法可以模拟该输入元素中的输入然后擦除它,以便至少激活“输入”事件,就像我之前说过,工作正常。

好的,错误是隧道视觉产生的问题。问题是,我的功能基于 w3schools 自动完成 javascript,其中自动完成功能仅在键入而不是单击输入元素时激活。

他们的自动完成功能甚至为整个文档添加了一个点击事件侦听器,它将关闭模拟的下拉元素,最终与输入元素的点击功能发生冲突,从而导致问题。

基本上我得改

document.addEventListener("click", function(e) {
    closeAllLists(e.target);
});

在自动完成功能中

document.addEventListener("click", function(e) {
    if (document.getElementsByClassName("doc_input")[0] != e.target) {
        closeAllLists(e.target);
    }
});