开发者问题收集

Javascript 输入监听器

2021-04-26
76

我有一个按每行最后一列的值排序的产品表。我希望当我单击某个输入时,相应的复选框直接变为选中状态。这样,当我单击“保存”按钮时,数据库中将只更新选定的产品。

原始代码中有太多与问题无关的内容,因此我将其简化为:

var c = 10;
var count = 1;
pageList.forEach(element => {
    document.getElementById("tabla_variantes").innerHTML+=`
        <tr style="background: white;">
            <th class="check_col" scope="row" style="padding: 0px; text-align: center; vertical-align: middle;">
                <input type="checkbox" value="${element.numero}" id="row${count}" name="row-check-pro">
            </th>
            <td> //image </td>
            <td> //product number </td>
            <td> //product name </td>
            <td> //product reference </td>
            <td> //product price </td>
            <td> //product stock </td>
            <td style="text-align:center; vertical-align: middle; padding: 8px 18px;">
                <input type="text" class="form-control text-end" id="posicion${element.numero}" value="${c}">
            </td>
        </tr>
    `;
    document.getElementById(`posicion${element.numero}`).addEventListener('input', (evt) => {
        console.log('run'); // Do something
        document.getElementById("row"+count).checked = true;
    });
    ++count;
    c += 10;
    if (c > list.length*10) c = 10;
});

如您所见,我尝试为每个输入添加一个监听器,但控制台上没有显示任何内容。

2个回答

你真的应该委托

此外,我建议使用 map 而不是连接到 DOM。

这是一个替换

const container = document.getElementById("tabla_variantes");
const pageList = [{numero:1},{numero:2},{numero:3}];

container.addEventListener('input', (evt) => {
  const tgt = evt.target; 
  if (tgt.name==="row-check-pro") {
    if (!tgt.checked) tgt.closest("tr").querySelector(".text-end").value="";
  }  
  if (tgt.classList.contains("text-end")) {
    tgt.closest("tr").querySelector("[name=row-check-pro]").checked = tgt.value.trim() != ""; 
  }  
});


var c = 10;
var count = 1;
container.innerHTML+= pageList.map(element => {
  const str = `<tr style="background: white;">
            <th class="check_col" scope="row" style="padding: 0px; text-align: center; vertical-align: middle;">
                <input type="checkbox" value="${element.numero}" id="row${count}" name="row-check-pro">
            </th>
            <td style="text-align:center; vertical-align: middle; padding: 8px 18px;">
                <input type="text" class="form-control text-end" id="posicion${element.numero}" value="${c}">
            </td>
        </tr>
    `;
    ++count;
    c += 10;
    if (c > pageList.length*10) c = 10;
    return str;
}).join("");
<table id="tabla_variantes">
</table>
mplungjan
2021-04-26

主要问题是您将 +=innerHTML 结合使用。这绝不是一个好主意。当您执行 x.innerHTML += str 时,浏览器必须处理 x 元素内的所有元素,构建 HTML 字符串,将该字符串返回给 JavaScript 代码,然后从 JavaScript 代码接受更新后的字符串, 拆除 x 的所有先前子元素,并将它们替换为通过解析新字符串创建的 子元素。这些元素的所有状态都将丢失,包括它们所拥有的任何事件处理程序。

最小更改是:

  1. 在字符串变量中构建所有 HTML
  2. 将其分配给 innerHTML
  3. 查找元素并向其添加事件处理程序

但您应该考虑使用事件委托和 DOM 遍历,而不是在每个单独的元素上使用处理程序。有关事件委托的更多信息,请参阅 Stack Overflow 上的这个答案 ,但简短的版本是您在共同祖先元素上处理事件,然后使用 event.target 确定事件针对的后代。

T.J. Crowder
2021-04-26