
本文介绍如何将传统的带 href 的 `` 标签点赞改为基于 `data-*` 属性 + ajax 的纯前端交互方案,避免 google 抓取时因 get 请求访问 post 路由导致的 405 错误,同时保持本地 cookie 记录与服务端计数的一致性。
要彻底解决“Google 抓取 /article/11?type=heart 导致 405 Method Not Allowed”的问题,核心思路是:*移除可被爬虫识别和访问的 php.cn/link/263b1243ca2dbeb358777ceabc4a2e4c"> 链接语义,改用无默认行为的元素(如 或 ` 属性携带业务参数,全部通过 JavaScript 发起受控的 AJAX 请求**。
✅ 推荐改造方案(安全、SEO 友好、体验一致)
1. HTML:替换 为 ,使用 data-* 存储上下文
✅ 优势:无 href,不会被搜索引擎当作可导航链接抓取;语义中立,无障碍友好(可加 role="button" 和 tabindex="0" 进一步增强)。
2. JavaScript:统一事件处理,动态构造请求
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.like-button').on('click', function(e) {
e.preventDefault();
const $btn = $(this);
const articleId = $btn.data('id');
const type = $btn.data('type');
// 防重复点击(可选)
if ($btn.hasClass('active')) return;
$.post(`/article/${articleId}/like`, { type }, function(response) {
if (response.message) {
const $counter = $btn.find('.comments-sub-header__item-icon-count');
const current = parseInt($counter.text()) || 0;
$counter.text(current + 1);
$btn.addClass('active');
}
}).fail(function(xhr) {
console.error('Like failed:', xhr.responseJSON?.message || 'Network error');
});
});
});? 关键点:
- 使用 POST(非 GET)确保 CSRF 安全,且与后端 postLike() 方法严格匹配;
- 路由统一改为 /article/{id}/like(RESTful 风格),避免 query 参数暴露在 URL 中;
- 前端不再拼接 ?type=xxx,所有参数走 request body,彻底消除爬虫误访风险。
3. 后端路由 & 控制器优化(Laravel 示例)
// routes/web.php
Route::post('/article/{id}/like', [ArticleController::class, 'postLike']);⚠️ 注意:原控制器逻辑已合理,无需修改,但建议补充响应状态码与错误健壮性:
public function postLike($id, Request $request) { $article = Article::findOrFail($id); // 更安全的 404 处理 $type = $request->input('type');
if (!in_array($type, ['heart', 'finger'])) {
return response()->json(['message' => 'Invalid like type'], 400);
}
if ($article->hasLikedToday($type)) {
return response()->json([
'message' => "You've already liked article {$id} with {$type} today.",
'liked' => true,
], 200);
}
$cookie = $article->setLikeCookie($type);
$article->increment("like_{$type}");
return response()->json([
'message' => "Liked article {$id} with {$type}.",
'liked' => true,
'count' => $article->{"getLike{$type->ucfirst()}Total"}(), // 动态获取最新总数(可选)
])->withCookie($cookie);}
立即学习“前端免费学习笔记(深入)”;
### ? 补充建议与注意事项 - **SEO 与可访问性**:若需支持无 JS 用户,可保留 `` 作为降级方案(``),但本场景通常为交互型点赞,无需强降级。 - **防刷机制**:当前 Cookie 方案仅限客户端校验,生产环境务必增加服务端 IP/用户 ID 级限频(如 Redis 计数器),防止恶意刷量。 - **缓存一致性**:页面首次加载时,`$article->getLikeHeartTotal()` 值来自数据库;AJAX 成功后仅前端 +1,若需实时同步其他用户点赞数,应引入 WebSocket 或轮询。 - **按钮状态反馈**:可添加 loading 状态(如禁用按钮、显示 spinner),提升用户体验。 通过以上改造,你将获得一个符合现代 Web 实践的点赞系统:无冗余链接、无爬虫干扰、CSRF 安全、响应明确、易于维护。











