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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:06:55