将商品列表页的收藏href链接改造为AJAX无刷新请求
改造AJAX无刷新收藏功能的完整方案
我明白你想把现有跳转式的收藏链接改成无刷新AJAX调用的需求——之前只接触过简单表单AJAX确实会有点懵,我结合你给出的代码一步步拆解改造方案,非常容易上手:
1. 前端修改:阻止默认跳转,绑定AJAX请求
首先给收藏链接添加点击事件,阻止它默认的页面跳转行为,转而发送AJAX请求。下面提供jQuery和原生JS两种实现方式,选你项目在用的即可:
jQuery版本
在页面底部或单独的JS文件中添加:
// 给所有收藏链接绑定点击事件 $('.a2f-link').on('click', function(e) { // 阻止默认跳转 e.preventDefault(); const $favLink = $(this); const requestUrl = $favLink.attr('href'); const $icon = $favLink.find('.fl_add'); const originalIconSrc = $icon.attr('src'); // 可选:显示加载状态 $icon.attr('src', 'images/icons/loading.gif'); // 发送AJAX请求 $.ajax({ url: requestUrl, type: 'GET', dataType: 'json', success: function(response) { if (response.status === 'success') { // 成功逻辑:显示提示+更新UI alert(response.message); // 也可以替换成你项目的messageStack组件 // 切换为已收藏图标 $icon.attr('src', 'images/icons/favourites-added.png'); // 更新收藏数量(如果有显示的话) $favLink.siblings('.a2f-value').text(parseInt($favLink.siblings('.a2f-value').text()) + 1); } else if (response.status === 'redirect') { // 需要登录时跳转登录页 window.location.href = response.redirectUrl; } else { // 错误提示+恢复原图标 alert(response.message); $icon.attr('src', originalIconSrc); } }, error: function() { alert('操作失败,请稍后重试'); $icon.attr('src', originalIconSrc); } }); });
原生JS版本
如果项目没引入jQuery,用原生JS实现:
document.addEventListener('DOMContentLoaded', function() { const favLinks = document.querySelectorAll('.a2f-link'); favLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const requestUrl = this.href; const icon = this.querySelector('.fl_add'); const originalSrc = icon.src; icon.src = 'images/icons/loading.gif'; fetch(requestUrl, { method: 'GET', headers: { 'Accept': 'application/json' } }) .then(res => res.json()) .then(data => { if (data.status === 'success') { alert(data.message); icon.src = 'images/icons/favourites-added.png'; const valueEl = this.parentElement.querySelector('.a2f-value'); valueEl.textContent = parseInt(valueEl.textContent) + 1; } else if (data.status === 'redirect') { window.location.href = data.redirectUrl; } else { alert(data.message); icon.src = originalSrc; } }) .catch(() => { alert('操作失败,请稍后重试'); icon.src = originalSrc; }); }); }); });
2. 后端修改:调整add_to_favourites动作的响应逻辑
原来的代码处理完后直接跳转页面,现在需要改成返回JSON格式的响应,让前端能根据结果做对应处理:
case 'add_to_favourites': // 初始化响应数据 $response = ['status' => 'error', 'message' => '未知错误']; if (isset($_GET['products_id'])) { $products_id = (int)$_GET['products_id']; if (zen_has_product_attributes($products_id)) { $response['message'] = sprintf(CAUTION_PRODUCT_HAS_ATTRIBUTES, zen_get_products_name($products_id)); } else { if (!(isset($_SESSION['customer_id']) && zen_not_null($_SESSION['customer_id']))) { // 需要登录时返回跳转地址 $response['status'] = 'redirect'; $response['redirectUrl'] = zen_href_link(FILENAME_LOGIN, '', 'SSL'); $response['message'] = CAUTION_LOGIN_REQUIRED_FOR_FAVOURITES; } else { $favourites = new favourites(); // 假设你的addToFavourites方法返回布尔值表示操作成功/失败 $isAdded = $favourites->addToFavourites($products_id, (FAVOURITES_SHOW_ON_ADD == 'true') ? 'favourites' : 'header'); if ($isAdded) { $response['status'] = 'success'; $response['message'] = '已添加到收藏夹!'; // 也可以用你项目的语言常量 } else { $response['message'] = '添加收藏失败,请稍后重试'; } } } } // 返回JSON响应,确保无多余输出 header('Content-Type: application/json'); echo json_encode($response); exit; // 必须终止后续代码执行,避免输出其他内容 break;
注意:如果你的
addToFavourites方法原本没有返回值,需要稍微修改它,让它在成功时返回true,失败时返回false。
3. 可选优化:增强链接的可扩展性
原有的add_to_favourites_link函数不需要大改,但可以给链接添加data属性,方便后续扩展功能:
public function add_to_favourites_link($products_id, $product_value) { if (!isset($this->icon)) { $this->icon = (FAVOURITES_LISTING_ICON == 'Font Awesome') ? FA_ADD_TO_FAVOURITES : zen_image(DIR_WS_IMAGES . 'icons/' . BUTTON_ADD_TO_FAVOURITES, BUTTON_ADD_TO_FAVOURITES_ALT, '', '','class="fl_add"'); } $page_link = zen_href_link($GLOBALS['current_page_base'], zen_get_all_get_params(array('products_id', 'action')) . 'products_id=' . (int)$products_id . '&action=add_to_favourites'); // 新增data-products-id属性,方便前端获取商品ID return ($this->favouritesEnabled) ? sprintf('<span class="a2f-wrap"><a title="%4$s" class="a2f-link" href="%2$s" data-products-id="%5$s">%3$s</a><span class="a2f-value">%1$s</span></span>', $product_value, $page_link, $this->icon, BUTTON_ADD_TO_FAVOURITES_ALT, (int)$products_id) : ''; }
4. 额外提示:处理已收藏状态
如果需要判断商品是否已被收藏,可以在生成链接时给已收藏的链接添加特殊class,前端点击时直接提示“已收藏”而不发请求:
// 在add_to_favourites_link函数中添加判断 $isFavourited = false; if (isset($_SESSION['customer_id'])) { $favourites = new favourites(); // 假设你有一个判断商品是否在收藏夹的方法 $isFavourited = $favourites->isProductInFavourites($products_id); } // 生成链接时添加额外class $linkClass = 'a2f-link' . ($isFavourited ? ' already-favourited' : '');
然后在前端点击事件中先判断这个class:
// jQuery版本示例 if ($favLink.hasClass('already-favourited')) { alert('该商品已在收藏夹中'); return; }
这样一步步改造后,就能实现完全无刷新的收藏功能啦,核心就是前端阻止跳转+发送AJAX,后端返回JSON响应,再根据响应更新页面UI。
内容的提问来源于stack exchange,提问作者Steph3071
相关产品推荐
相关产品推荐

