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

如何通过AJAX实现从MySQL表及数据库中删除用户

问题:原生JS实现MySQL表格行删除功能失败

我正在构建一个带CRUD功能的MySQL用户表格,用原生JS写代码时遇到问题:点击每行的删除按钮,无法同时从前端表格和数据库中删除对应用户。表格每行代表一个用户,每行都有删除按钮,不知道怎么给每个按钮绑定对应用户并实现删除操作。下面是我的index.js和delete.php代码:


现有代码

index.js

document.addEventListener('DOMContentLoaded', function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "data.php", true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            var data = JSON.parse(xhr.responseText);
            if (Array.isArray(data) && data.length === 0) {
                alert('No record found');
            } else {
                var tableBody = "";
                data.forEach(function(row) {
                    tableBody += "<tr>";
                    tableBody += "<td id='user-id'>" + row.id +  "</td>";
                    tableBody += "<td>" + row.name + "</td>";
                    tableBody += "<td>" + row.email + "</td>";
                    tableBody += "<td>" + row.city + "</td>";
                    tableBody += "<td> <button id='edit' class='btn btn-primary'>Edit</button> <button id='delete' class='btn btn-danger'>Delete</button> </td>" 
                    tableBody += "</tr>";
                });
                document.getElementById("tbody").innerHTML = tableBody;
                console.warn(xhr.responseText)
            }
            
        } else if (xhr.readyState === 4 && xhr.status !== 200) {
            alert("An error occurred while fetching the data.");
        }
    };
    xhr.send();       
});

// 提交新用户到数据库
const saveForm = document.querySelector("#save-data");

saveForm.addEventListener('submit', function(e) {
  e.preventDefault(); // 阻止表单默认提交行为
  const modalMess = document.getElementById("response");

  const userData = {
    name: document.querySelector('#name').value,
    email: document.querySelector('#email').value,
    city: document.querySelector('#city').value
  };

  const jsonData = JSON.stringify(userData);

  const xhr = new XMLHttpRequest();
  xhr.open('POST', 'adduser.php');
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.onload = function() {
    if (xhr.status === 200) {
        modalMess.innerHTML = xhr.responseText
      console.log(xhr.responseText);
    } else {
      console.error('Error: ' + xhr.status);
    }
  };

  xhr.send(jsonData);
});

// 获取所有删除按钮并绑定事件
const deleteButtons = document.querySelectorAll('#delete');
deleteButtons.forEach(function(deleteButton) {
  deleteButton.addEventListener('click', function() {
    const userId = this.closest('tr').querySelector('#user-id').textContent;
    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'delete.php');
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.onload = function() {
      if (xhr.status === 200) {
        console.log(xhr.responseText);
      } else {
        console.error('Error: ' + xhr.status);
      }
    };
    xhr.send(JSON.stringify({ id: userId }));
  });
});

delete.php

<?php
header('Content-Type:application/json');
header('Access-control-Allow-Origin:*');
header('Access-Control-Allow-Methods:DELETE');
header('Access-Control-Allow-Headers:Acess-Control-Allow-Headers,Content-Type,Acess-Control-Allow-Methods,Authorization,X-Requested-With');

$data = json_decode(file_get_contents("php://input"), true);

$student_id = $data['id'];

include "connect.php";
$sql = "DELETE FROM clients WHERE id={$student_id}";

if (mysqli_query($conn, $sql)) {
   echo json_encode(array("message" => "Delete sucessfully", "status" => true));
} else {
   echo json_encode(array("message" => "not deleted", "status" => false));
}
?>

问题原因及修复方案

1. 重复ID导致DOM选择失败

  • 问题:生成表格时,每行的用户ID单元格用了id='user-id',删除按钮用了id='delete'。ID在DOM中必须唯一,重复ID会导致querySelector只能选中第一个匹配元素。
  • 修复:把这些重复ID改成class,比如class="user-id"和class="delete-btn"。

2. 事件绑定时机错误

  • 问题:删除按钮的事件绑定代码在DOMContentLoaded外面执行,但表格是通过AJAX异步生成的,执行绑定代码时按钮还没渲染到页面上,所以监听器没生效。
  • 修复:使用事件委托(给父元素tbody绑定事件,监听子元素的点击),或者把绑定代码移到表格生成完成的回调里。事件委托更适合动态生成的元素。

3. SQL注入风险

  • 问题:PHP中直接把用户传入的ID拼到SQL语句里,存在SQL注入漏洞。
  • 修复:使用MySQLi预处理语句,参数化查询。

4. CORS头拼写错误

  • 问题:Acess-Control拼写错误,正确应该是Access-Control,会导致跨域请求失败(如果是跨域场景)。

5. 前端未同步更新表格

  • 问题:删除成功后没有移除页面上对应的表格行,用户看不到删除效果。
  • 修复:在AJAX的onload回调中,判断删除成功后,移除当前点击按钮所在的<tr>元素。

修改后的完整代码

index.js

document.addEventListener('DOMContentLoaded', function() {
    // 加载用户数据生成表格
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "data.php", true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            var data = JSON.parse(xhr.responseText);
            if (Array.isArray(data) && data.length === 0) {
                alert('No record found');
            } else {
                var tableBody = "";
                data.forEach(function(row) {
                    tableBody += "<tr>";
                    // 把id改成class
                    tableBody += "<td class='user-id'>" + row.id +  "</td>";
                    tableBody += "<td>" + row.name + "</td>";
                    tableBody += "<td>" + row.email + "</td>";
                    tableBody += "<td>" + row.city + "</td>";
                    // 删除按钮用class,新增data-id存储用户ID
                    tableBody += "<td> <button class='btn btn-primary edit-btn'>Edit</button> <button class='btn btn-danger delete-btn' data-id='" + row.id + "'>Delete</button> </td>" 
                    tableBody += "</tr>";
                });
                document.getElementById("tbody").innerHTML = tableBody;
            }
        } else if (xhr.readyState === 4 && xhr.status !== 200) {
            alert("An error occurred while fetching the data.");
        }
    };
    xhr.send();       

    // 事件委托:给tbody绑定删除按钮点击事件
    document.getElementById('tbody').addEventListener('click', function(e) {
        if (e.target.classList.contains('delete-btn')) {
            const deleteBtn = e.target;
            const userId = deleteBtn.dataset.id; // 直接从data-id获取ID,更高效
            const row = deleteBtn.closest('tr');

            // 发送删除请求
            const xhr = new XMLHttpRequest();
            xhr.open('DELETE', 'delete.php'); // 用DELETE方法,和后端设置一致
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onload = function() {
                if (xhr.status === 200) {
                    const response = JSON.parse(xhr.responseText);
                    if (response.status) {
                        row.remove(); // 删除成功后移除表格行
                        alert(response.message);
                    } else {
                        alert('删除失败:' + response.message);
                    }
                } else {
                    alert('请求失败,状态码:' + xhr.status);
                }
            };
            xhr.send(JSON.stringify({ id: userId }));
        }
    });
});

// 提交新用户到数据库
const saveForm = document.querySelector("#save-data");
saveForm.addEventListener('submit', function(e) {
  e.preventDefault(); // 阻止表单默认跳转
  const modalMess = document.getElementById("response");

  const userData = {
    name: document.querySelector('#name').value,
    email: document.querySelector('#email').value,
    city: document.querySelector('#city').value
  };

  const jsonData = JSON.stringify(userData);

  const xhr = new XMLHttpRequest();
  xhr.open('POST', 'adduser.php');
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.onload = function() {
    if (xhr.status === 200) {
        modalMess.innerHTML = xhr.responseText;
        // 提交成功后重新加载表格数据
        location.reload();
    } else {
      console.error('Error: ' + xhr.status);
      modalMess.innerHTML = '提交失败,请重试';
    }
  };

  xhr.send(jsonData);
});

delete.php

<?php
header('Content-Type:application/json');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:DELETE');
// 修正拼写错误
header('Access-Control-Allow-Headers:Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods,Authorization,X-Requested-With');

$data = json_decode(file_get_contents("php://input"), true);

// 检查ID是否存在
if(!isset($data['id']) || empty($data['id'])){
    echo json_encode(array("message" => "缺少用户ID", "status" => false));
    exit;
}

$student_id = $data['id'];

include "connect.php";
// 使用预处理语句防止SQL注入
$sql = "DELETE FROM clients WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, "i", $student_id); // i表示整数类型

if (mysqli_stmt_execute($stmt)) {
    // 检查是否有行被影响
    if(mysqli_stmt_affected_rows($stmt) > 0){
        echo json_encode(array("message" => "删除成功", "status" => true));
    }else{
        echo json_encode(array("message" => "未找到该用户", "status" => false));
    }
} else {
    echo json_encode(array("message" => "删除失败:".mysqli_error($conn), "status" => false));
}

// 关闭语句和连接
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:47:00