Codeigniter博客中jQuery $.ajax与confirm()配合删除功能失效排查
我正在基于CodeIgniter 3.1.8和Bootstrap 4开发一个基础博客应用,实现文章删除功能时,使用jQuery的$.ajax方法遇到了问题,相关代码无法正常触发删除操作。
文章视图代码:
<table class="table table-striped table-sm border-0"> <thead> <tr> <th>#</th> <th class="w-50">Title</th> <th>Publication date</th> <th class="text-center">Actions</th> </tr> </thead> <tbody> <?php foreach ($posts as $index => $post): ?> <tr id="<?php echo $post->id; ?>"> <td class="text-right"><?php $count = $index + 1; echo $count + $offset; ?></td> <td><?php echo $post->title; ?></td> <td><?php echo nice_date($post->created_at, 'D, M d, Y'); ?></td> <td class="text-center"> <div class="btn-group btn-group-sm" role="group"> <a href="<?php echo base_url('posts/post/') . $post->id; ?>" class="btn btn-success"><i class="fa fa-eye"></i> View</a> <?php if($this->session->userdata('is_logged_in') && $this->session->userdata('user_id') == $post->author_id) : ?> <a href="<?php echo base_url('posts/edit/') . $post->id; ?>" class="btn btn-success"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" id="delete_post" data-id="<?php echo $post->id ?>" class="ajax-btn btn btn-success"><i class="fa fa-trash"></i> Delete</a> <?php else: ?> <a href="#" class="btn btn-success disabled"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" id="delete_post" class="btn btn-success disabled"><i class="fa fa-trash"></i> Delete</a> <?php endif; ?> </div> </td> </tr> <?php endforeach ?> </tbody> </table>
jQuery AJAX 删除代码:
//Delete Posts $('#delete_post').on('click', function(evt){ evt.preventDefault(); var deleteUrl = $(this).attr('href'); var id = $(this).data('id'); if(confirm('Delete this post?')) { if ($(this).hasClass("ajax-btn")) { $.ajax({ url: 'posts/delete/' + id, method: 'GET', dataType: 'html', success: function(deleteMsg){ $('tr#' + id).fadeOut('250'); $('#delete_msg').html('<p>Post successfully deleted</p>'); $('#delete_msg').slideDown(250).delay(2500).slideUp(250); } }); } else { window.location.href = deleteUrl; } } });
问题原因分析及解决方案
1. 重复的ID属性(最核心问题)
HTML规范要求id属性在整个DOM中必须唯一,但你的视图里每个删除按钮都用了id="delete_post"。这会导致jQuery的$('#delete_post').on('click')只绑定第一个匹配的按钮,后面所有删除按钮的点击事件都不会触发。
解决方法:
把id="delete_post"改成类选择器,比如class="delete-post ajax-btn btn btn-success"(有权限的按钮),禁用按钮改成class="delete-post btn btn-success disabled"。修改后的视图片段:
<?php if($this->session->userdata('is_logged_in') && $this->session->userdata('user_id') == $post->author_id) : ?> <a href="<?php echo base_url('posts/edit/') . $post->id; ?>" class="btn btn-success"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" data-id="<?php echo $post->id ?>" class="delete-post ajax-btn btn btn-success"><i class="fa fa-trash"></i> Delete</a> <?php else: ?> <a href="#" class="btn btn-success disabled"><i class="fa fa-pencil-square-o"></i> Edit</a> <a href="#" class="delete-post btn btn-success disabled"><i class="fa fa-trash"></i> Delete</a> <?php endif; ?>
然后修改jQuery事件绑定,使用类选择器+事件委托(确保动态加载的文章也能触发事件):
// 事件委托绑定到tbody,兼容动态加载的元素 $('tbody').on('click', '.delete-post', function(evt){ evt.preventDefault(); var $this = $(this); var id = $this.data('id'); // 跳过禁用按钮,避免无效操作 if($this.hasClass('disabled')) return; if(confirm('Delete this post?')) { if ($this.hasClass("ajax-btn")) { // 用base_url生成绝对路径,避免相对路径错误 var deleteUrl = '<?php echo base_url('posts/delete/'); ?>' + id; $.ajax({ url: deleteUrl, method: 'POST', // 推荐用POST请求删除操作,符合REST规范且避免缓存 dataType: 'html', success: function(deleteMsg){ $('tr#' + id).fadeOut(250, function(){ // 动画结束后移除元素,清理DOM $(this).remove(); }); $('#delete_msg').html('<p>Post successfully deleted</p>'); $('#delete_msg').slideDown(250).delay(2500).slideUp(250); }, error: function(xhr){ // 增加错误处理,方便调试 alert('删除失败,请重试'); console.log(xhr.responseText); } }); } else { window.location.href = $this.attr('href'); } } });
2. AJAX请求的URL路径问题
原代码中url: 'posts/delete/' + id是相对路径,如果当前页面不在网站根路径(比如http://example.com/blog/posts),请求URL会变成错误的http://example.com/blog/posts/delete/1,而非正确的http://example.com/posts/delete/1。
解决方法:
用CodeIgniter的base_url()生成绝对路径,确保请求地址始终正确,就像修改后的JS代码那样。
3. HTTP请求方法的合理性
删除操作属于修改服务器资源的行为,不建议使用GET请求——GET会被浏览器缓存,且不符合RESTful设计规范。建议改成method: 'POST',同时在CodeIgniter控制器中对应处理POST请求:
// Posts控制器的delete方法示例 public function delete($id){ // 校验用户登录状态 if(!$this->session->userdata('is_logged_in')){ redirect('login'); } // 执行删除逻辑 $this->post_model->delete_post($id); // 返回成功响应 echo 'success'; }
内容的提问来源于stack exchange,提问作者Razvan Zamfir

