如何在Laravel中实现异步点赞请求?避免页面刷新
实现异步点赞(无页面刷新)的解决方案
问题背景
当前点赞逻辑采用同步POST请求,触发页面刷新,虽通过Cookie恢复滚动位置,但仍需实现完全异步的后台处理,彻底避免页面刷新。
现有后端控制器代码:
class LikeController extends Controller { public function like(Post $post) { $attributes = [ ['user_id', '=', auth()->user()->id], ['post_id', '=', $post->id] ]; $like = Like::where($attributes); if($like->exists()) { $like->delete(); } else { Like::create(['user_id' => auth()->user()->id, 'post_id' => $post->id]); } return redirect()->to(url()->previous()); } }
路由配置:
Route::post('like/{post}', [LikeController::class, 'like']);
现有前端JS(仅恢复滚动位置):
$(window).on("scroll", function(e) { $.cookie("tempScrollTop", $(window).scrollTop()); }); $(".like-form").each(function() { $(this).submit(function(e) { $.cookie("action", 'like', {path: '/'}); }) }); $(window).on("load", function (e) { if ($.cookie("tempScrollTop") && $.cookie('action') === 'like') { $(window).scrollTop($.cookie("tempScrollTop")); $.cookie("action", '', {path: '/'}); } })
实现步骤
1. 后端控制器调整
将返回重定向改为JSON响应,传递操作结果(点赞状态、当前点赞数等):
class LikeController extends Controller { public function like(Post $post) { $userId = auth()->id(); $likeExists = Like::where('user_id', $userId) ->where('post_id', $post->id) ->exists(); if ($likeExists) { Like::where('user_id', $userId)->where('post_id', $post->id)->delete(); return response()->json([ 'success' => true, 'liked' => false, 'likeCount' => $post->likes()->count() ]); } else { Like::create(['user_id' => $userId, 'post_id' => $post->id]); return response()->json([ 'success' => true, 'liked' => true, 'likeCount' => $post->likes()->count() ]); } } }
2. 前端JS修改(阻止同步提交,改用AJAX)
删除原滚动恢复代码,替换为异步请求逻辑,实时更新页面点赞状态:
$(".like-form").on('submit', function(e) { // 阻止表单默认同步提交行为 e.preventDefault(); const form = $(this); const url = form.attr('action'); const likeButton = form.find('.like-button'); const likeCountElement = form.find('.like-count'); $.ajax({ url: url, method: 'POST', data: form.serialize(), // 携带CSRF令牌等表单数据 success: function(response) { if (response.success) { // 更新按钮状态(图标/文字) if (response.liked) { likeButton.addClass('liked').text('取消点赞'); } else { likeButton.removeClass('liked').text('点赞'); } // 更新点赞数显示 likeCountElement.text(response.likeCount); } }, error: function(xhr) { if (xhr.status === 401) { alert('请先登录再进行点赞操作'); // 可选:跳转到登录页 // window.location.href = '/login'; } else { alert('点赞操作失败,请稍后重试'); } } }); });
3. 视图层优化(确保CSRF令牌与状态初始化)
Laravel需携带CSRF令牌验证POST请求,同时初始化按钮初始状态:
<form class="like-form" action="/like/{{ $post->id }}" method="POST"> @csrf <button type="submit" class="like-button {{ auth()->check() && auth()->user()->liked($post) ? 'liked' : '' }}"> {{ auth()->check() && auth()->user()->liked($post) ? '取消点赞' : '点赞' }} </button> <span class="like-count">{{ $post->likes->count() }}</span> </form>
需在User模型中添加关联方法支持状态判断:
// User模型内 public function likes() { return $this->hasMany(Like::class); } public function liked(Post $post) { return $this->likes()->where('post_id', $post->id)->exists(); }
内容的提问来源于stack exchange,提问作者infinite789
相关产品推荐
相关产品推荐

