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

将商品列表页的收藏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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:39