You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决JavaScript实现MySQL记录删除按钮的报错问题

MySQL表镜像页面删除按钮功能异常

场景概述

我正在构建一个用于镜像MySQL服务器中某张表的网页,表格每行配有两个按钮,其中红色按钮用于删除服务器中的对应记录。页面效果为:表格展示了MySQL表中的数据,包含Código、Tipo de Movimento等列,每行末尾配有绿色确认按钮和红色删除按钮。

现有实现代码

数据加载与表格生成代码

async function loadData(){
    var result = await fetch("http://localhost:8080/dados",
        {
            method:"POST",
            headers:{'Content-Type': "application/json"},
            body:JSON.stringify({command: "fetch", codMovimento: 0})
        }
    )
    tableJson = await result.json()
    console.log(tableJson)

    var table = document.getElementById("minhaTabela");

    table.innerHTML += "<tbody>"
    table.innerHTML += `<thead class="thead-dark">
    <tr>
        <th scope="col">Código</th>
        <th scope="col">Tipo de Movimento</th>
        <th scope="col">Técnico</th>
        <th scope="col" style="width:350px;">Peça</th>
        <th scope="col">Código da Peça</th>
        <th scope="col">Origem</th>
        <th scope="col">Destino</th>
        <th scope="col" style="text-align: center;">Quantidade</th>
        <th scope="col"></th>
        <th scope="col"></th>
    </tr>
    </thead>`

    for(var i=0; i < tableJson.length; i++){
        table.innerHTML +=
        `
        <tr>
            <th scope="row">${tableJson[i].CodMovimento}</th>
            <td>${tableJson[i].TipoMovimento}</td>
            <td>${tableJson[i].Tecnico}</td>
            <td>${tableJson[i].NomePeca}</td>
            <td>${tableJson[i].CodPeca}</td>
            <td>${tableJson[i].Origem}</td>
            <td>${tableJson[i].Destino}</td>
            <td style="text-align: center;">1</td>
            <td>
                <button type="button" class="btn btn-success" id="approveButton${i}">
                <img src="/assets/check.svg" alt="Bootstrap" width="32" height="32">
                </button>
            </td>
            <td>
                <button type="button" class="btn btn-danger" id="refuseButton${i}">
                <img src="/assets/x.svg" alt="Bootstrap" width="32" height="32">
                </button>
            </td>
        </tr>
        `
    }

    table.innerHTML += "</tbody>"

    declareButtons(tableJson)

}

loadData()

删除按钮绑定代码

async function declareButtons(tableJson){
    const approveButtons = []
    const refuseButtons = []
    
    for(var i=0; i < tableJson.length; i++){
    
        approveButtons.push(document.getElementById(`approveButton${i}`));
        approveButtons[i].onclick = async function(){
            console.log("Teste234")
        }
    
        refuseButtons.push(document.getElementById(`refuseButton${i}`));
        refuseButtons[i].onclick = async function(tableJson){

            console.log(tableJson[i].CodMovimento)
            var result = await fetch("http://localhost:8080/dados",
                {
                    method:"POST",
                    headers:{'Content-Type': "application/json"},
                    body:JSON.stringify({command: "delete", codMovimento: tableJson[i].CodMovimento})
                }
            )

            location.reload()

        }
        
    }
}

问题现象

点击红色删除按钮时,控制台抛出Uncaught TypeError: Cannot read properties of undefined (reading 'CodMovimento')错误;添加try/catch块后报错不再显示,但删除记录的逻辑仍未执行。


解决方案

问题根源

  1. 闭包陷阱:使用var声明循环变量i,所有点击函数共享同一个i引用,点击时i已变为循环结束后的最大值,导致tableJson[i]为undefined。
  2. 参数覆盖:点击函数的参数tableJson覆盖了外部作用域的同名变量,内部访问的不是原数据数组。

修复方案1:修复闭包与参数问题

async function declareButtons(tableJson){
    const approveButtons = []
    const refuseButtons = []
    
    // 用let声明i,每次循环创建独立作用域
    for(let i=0; i < tableJson.length; i++){
    
        approveButtons.push(document.getElementById(`approveButton${i}`));
        approveButtons[i].onclick = async function(){
            console.log("Teste234")
        }
    
        refuseButtons.push(document.getElementById(`refuseButton${i}`));
        // 移除多余的tableJson参数,避免覆盖外部变量
        refuseButtons[i].onclick = async function(){
            const codMovimento = tableJson[i].CodMovimento;
            console.log(codMovimento);
            try {
                const result = await fetch("http://localhost:8080/dados",
                    {
                        method:"POST",
                        headers:{'Content-Type': "application/json"},
                        body:JSON.stringify({command: "delete", codMovimento: codMovimento})
                    }
                );
                // 检查请求是否成功
                if(!result.ok){
                    throw new Error(`请求失败:${result.status}`);
                }
                location.reload();
            } catch(err) {
                console.error("删除失败:", err);
                // 可在此添加用户友好的错误提示
            }
        }
    }
}

修复方案2:事件委托(更推荐)

无需循环绑定事件,直接在表格上绑定事件监听,通过事件冒泡判断点击目标,避免闭包问题且性能更优:

// 替换原declareButtons函数
function setupTableEvents() {
    const table = document.getElementById("minhaTabela");
    table.addEventListener("click", async function(e) {
        const targetBtn = e.target.closest("button");
        if(!targetBtn) return;
        
        // 判断是否为删除按钮
        if(targetBtn.classList.contains("btn-danger")){
            // 获取当前行的CodMovimento
            const row = targetBtn.closest("tr");
            const codMovimento = row.querySelector("th").textContent;
            try {
                const result = await fetch("http://localhost:8080/dados",
                    {
                        method:"POST",
                        headers:{'Content-Type': "application/json"},
                        body:JSON.stringify({command: "delete", codMovimento: parseInt(codMovimento)})
                    }
                );
                if(!result.ok){
                    throw new Error(`请求失败:${result.status}`);
                }
                location.reload();
            } catch(err) {
                console.error("删除失败:", err);
            }
        } else if(targetBtn.classList.contains("btn-success")){
            console.log("Teste234");
        }
    });
}

// 在loadData函数中替换declareButtons(tableJson)为:
// setupTableEvents();

额外优化建议

  1. 为loadData中的tableJson添加局部变量声明:const tableJson = await result.json();,避免污染全局作用域。
  2. 生成表格时,先构建完整HTML字符串再一次性赋值,减少DOM操作次数:
async function loadData(){
    const result = await fetch("http://localhost:8080/dados",
        {
            method:"POST",
            headers:{'Content-Type': "application/json"},
            body:JSON.stringify({command: "fetch", codMovimento: 0})
        }
    )
    const tableJson = await result.json()
    console.log(tableJson)

    const table = document.getElementById("minhaTabela");
    let html = `<tbody>
        <thead class="thead-dark">
            <tr>
                <th scope="col">Código</th>
                <th scope="col">Tipo de Movimento</th>
                <th scope="col">Técnico</th>
                <th scope="col" style="width:350px;">Peça</th>
                <th scope="col">Código da Peça</th>
                <th scope="col">Origem</th>
                <th scope="col">Destino</th>
                <th scope="col" style="text-align: center;">Quantidade</th>
                <th scope="col"></th>
                <th scope="col"></th>
            </tr>
        </thead>`;

    for(let i=0; i < tableJson.length; i++){
        html += `
        <tr>
            <th scope="row">${tableJson[i].CodMovimento}</th>
            <td>${tableJson[i].TipoMovimento}</td>
            <td>${tableJson[i].Tecnico}</td>
            <td>${tableJson[i].NomePeca}</td>
            <td>${tableJson[i].CodPeca}</td>
            <td>${tableJson[i].Origem}</td>
            <td>${tableJson[i].Destino}</td>
            <td style="text-align: center;">1</td>
            <td>
                <button type="button" class="btn btn-success">
                <img src="/assets/check.svg" alt="Bootstrap" width="32" height="32">
                </button>
            </td>
            <td>
                <button type="button" class="btn btn-danger">
                <img src="/assets/x.svg" alt="Bootstrap" width="32" height="32">
                </button>
            </td>
        </tr>`;
    }

    html += "</tbody>";
    table.innerHTML = html;

    setupTableEvents();
}

loadData()

内容的提问来源于stack exchange,提问作者Linx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 23:18:22