连续调用AJAX函数后动态元素点击事件失效问题求助
问题:排序后点击产品元素无响应
我有两个AJAX函数:第一个用于对数据库中的数据进行排序(A-Z、Z-A等),第二个用于点击指定ID的.product元素后展示对应数据库数据。两个脚本单独运行时均正常,但先对元素列表进行排序后,再点击其中的.product元素却没有任何反应;未排序时点击能正常展示内容,排序后刷新页面再点击也能正常展示内容。
相关代码如下:
前端脚本
// head tag <script> $(function() { $('#sort_form').on('submit', function(e) { e.preventDefault(); $.ajax({ type: "post", url: 'php/display.php', data: new FormData(this), processData: false, contentType: false, success: function(response) { $(".recipe-list").html(response); }, error: function() { } }); }); }); $(function() { $('.product').on('click', function(e) { var product = $(this).attr('id'); $.ajax({ type: "post", url: 'php/recipe-container.php', data: { "name": product }, success: function(response) { $(".display_recipe").html(response); } }); }); }); </script>
HTML结构
<form method="POST" id="sort_form" enctype='multipart/form-data'> <input type="submit" id="sort_submit"> <select name="sort" id="sort" onchange="$('#sort_submit').submit()"> <optgroup label="Alphabetically"> <option value="alphabet">A-Z</option> <option value="alphabet_rev">Z-A</option> </optgroup> <optgroup label="Whole"> <option value="kcal_low_all">Kcal (to highest)</option> <option value="kcal_high_all">Kcal (to lowest)</option> </optgroup> </select> </form> <div class="recipe-list"> <?php require "php/display.php"; ?> </div> <div class="display_recipe"></div>
后端核心代码(部分)
// display.php function display_content($dish_type){ require "sort-list.php"; $con = mysqli_connect("localhost", "root", "", "cookbook"); $res = mysqli_query($con,$sql); while($row = mysqli_fetch_assoc($res)) { $recipename = $row['name']; // ... 计算逻辑 echo "<p id='".$recipename."' class='product'>".$recipename."</p>"; // ... 输出其他信息 } mysqli_close($con); } // ... 其他函数
// recipe-container.php function display(){ $con = mysqli_connect("localhost", "root", "", "cookbook"); $product = $_POST["name"]; $sql = "SELECT * FROM product WHERE name = '$product'"; $res = mysqli_query($con,$sql); // ... 输出数据逻辑 }
原因分析
你当前的点击事件绑定方式$('.product').on('click', ...)只会给页面加载时已存在的DOM元素绑定事件。排序操作通过AJAX重新渲染了.recipe-list内的内容,新生成的.product元素是后续动态添加的,没有被绑定点击事件,因此点击无响应。
解决方案
使用事件委托(Event Delegation),将点击事件绑定到一个始终存在的父元素(比如.recipe-list)上,由父元素监听子元素的点击行为。这样无论子元素是初始加载还是动态生成的,都能触发事件。
修改后的前端脚本中,点击事件部分替换为:
$(function() { // 事件委托:绑定到父元素 .recipe-list $(".recipe-list").on('click', '.product', function(e) { var product = $(this).attr('id'); $.ajax({ type: "post", url: 'php/recipe-container.php', data: { "name": product }, success: function(response) { $(".display_recipe").html(response); } }); }); });
额外提示
你的PHP代码存在SQL注入风险,直接将用户输入(比如$_POST["name"]、$_POST["sort"])拼接到SQL语句中非常危险。建议使用MySQLi的预处理语句(Prepared Statements)来避免,示例如下:
修改recipe-container.php的查询逻辑:
function display(){ $con = mysqli_connect("localhost", "root", "", "cookbook"); $product = $_POST["name"]; // 使用预处理语句 $sql = "SELECT * FROM product WHERE name = ?"; $stmt = mysqli_prepare($con, $sql); mysqli_stmt_bind_param($stmt, "s", $product); mysqli_stmt_execute($stmt); $res = mysqli_stmt_get_result($stmt); while($row = mysqli_fetch_assoc($res)) { // ... 输出数据逻辑 } mysqli_stmt_close($stmt); mysqli_close($con); }
修改sort-list.php的查询逻辑:
$sort = isset($_POST["sort"]) ? $_POST["sort"] : "alphabet_p"; // 先定义基础SQL,后续根据sort参数调整排序规则 $sql = "SELECT * FROM product WHERE type = ?"; $params = [$dish_type]; $paramType = "s"; $kcal_query = "(fat * 9 + carbohydrates * 4 + fiber * 2 + protein * 4)"; switch ($sort) { case "alphabet": $sql .= " ORDER BY name"; break; case "alphabet_rev": $sql .= " ORDER BY name DESC"; break; case "kcal_low_all": $sql .= " ORDER BY $kcal_query"; break; case "kcal_high_all": $sql .= " ORDER BY $kcal_query DESC"; break; } // 执行预处理语句(在display_content中执行) // 在display_content中: // $stmt = mysqli_prepare($con, $sql); // mysqli_stmt_bind_param($stmt, $paramType, ...$params); // mysqli_stmt_execute($stmt); // $res = mysqli_stmt_get_result($stmt);
内容的提问来源于stack exchange,提问作者Astw41
相关产品推荐
相关产品推荐

