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

如何正确整合WooCommerce筛选与无限加载两个Ajax请求(无插件)

问题根源分析

筛选功能生效后,无限加载的Ajax请求没有携带当前的筛选条件(尺寸、颜色、排序方式),后端PHP接收到的还是初始默认查询参数,所以返回未筛选的分页数据。另外,筛选后商品总数可能变化,无限加载的终止条件(是否还有更多页)也需要同步更新。

解决思路
  1. 用全局变量存储筛选参数和分页状态,每次无限加载时携带这些参数
  2. 筛选完成后重置无限加载的页码、是否还有更多数据的状态
  3. 后端PHP统一处理筛选和无限加载的参数,生成一致的查询逻辑
代码实现

前端JS部分

// 全局存储筛选参数与分页状态
let filterParams = {
    size: '',
    color: '',
    orderby: 'date',
    order: 'desc',
    paged: 1
};
let hasMore = true;
let isLoading = false;

// 筛选表单提交逻辑
document.querySelector('.filter-form').addEventListener('submit', function(e) {
    e.preventDefault();
    // 捕获当前筛选参数
    filterParams.size = document.querySelector('#size-filter').value;
    filterParams.color = document.querySelector('#color-filter').value;
    filterParams.orderby = document.querySelector('#orderby-filter').value;
    filterParams.order = document.querySelector('#order-filter').value;
    filterParams.paged = 1; // 筛选后重置页码为第一页
    hasMore = true;
    isLoading = false;

    // 发起筛选请求
    fetch('/wp-admin/admin-ajax.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            action: 'filter_products',
            ...filterParams
        })
    })
    .then(response => response.text())
    .then(html => {
        // 替换商品列表容器内容
        document.querySelector('.products-container').innerHTML = html;
        // 更新是否还有更多页的状态
        const totalPages = parseInt(document.querySelector('#total-pages').value);
        hasMore = filterParams.paged < totalPages;
    })
    .catch(error => console.error('筛选请求失败:', error));
});

// 滚动触发无限加载
window.addEventListener('scroll', function() {
    if (!hasMore || isLoading) return;
    // 滚动到页面底部200px内时触发加载
    if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 200) {
        loadMoreProducts();
    }
});

// 加载更多商品逻辑
function loadMoreProducts() {
    isLoading = true;
    filterParams.paged++; // 页码自增

    fetch('/wp-admin/admin-ajax.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            action: 'load_more_products',
            ...filterParams
        })
    })
    .then(response => response.text())
    .then(html => {
        // 追加商品到列表容器
        document.querySelector('.products-container').insertAdjacentHTML('beforeend', html);
        // 更新加载状态
        const totalPages = parseInt(document.querySelector('#total-pages').value);
        hasMore = filterParams.paged < totalPages;
        isLoading = false;
    })
    .catch(error => {
        console.error('加载更多失败:', error);
        isLoading = false;
    });
}

后端PHP部分(添加到主题functions.php)

// 筛选商品的Ajax回调
add_action('wp_ajax_filter_products', 'filter_products_callback');
add_action('wp_ajax_nopriv_filter_products', 'filter_products_callback');

function filter_products_callback() {
    $args = array(
        'post_type' => 'product',
        'posts_per_page' => 6,
        'paged' => isset($_POST['paged']) ? intval($_POST['paged']) : 1,
        'orderby' => isset($_POST['orderby']) ? sanitize_text_field($_POST['orderby']) : 'date',
        'order' => isset($_POST['order']) ? sanitize_text_field($_POST['order']) : 'desc',
        'tax_query' => array(),
    );

    // 处理尺寸筛选(替换为你的尺寸分类法slug)
    if (!empty($_POST['size'])) {
        $args['tax_query'][] = array(
            'taxonomy' => 'product_size',
            'field' => 'slug',
            'terms' => sanitize_text_field($_POST['size']),
        );
    }

    // 处理颜色筛选(替换为你的颜色分类法slug)
    if (!empty($_POST['color'])) {
        $args['tax_query'][] = array(
            'taxonomy' => 'product_color',
            'field' => 'slug',
            'terms' => sanitize_text_field($_POST['color']),
        );
    }

    // 多分类筛选时设置关系为AND
    if (count($args['tax_query']) > 1) {
        $args['tax_query']['relation'] = 'AND';
    }

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            // 输出商品模板(可替换为你的商品模板代码)
            echo '<div class="product-item">';
            the_title('<h3 class="product-title">', '</h3>');
            the_post_thumbnail('medium', ['class' => 'product-thumb']);
            echo '</div>';
        }
        // 输出总页数隐藏标记,供前端判断是否还有更多数据
        echo '<input type="hidden" id="total-pages" value="' . $query->max_num_pages . '">';
    } else {
        echo '<p class="no-products">没有找到匹配的商品</p>';
        echo '<input type="hidden" id="total-pages" value="1">';
    }

    wp_reset_postdata();
    wp_die();
}

// 无限加载商品的Ajax回调,直接复用筛选逻辑
add_action('wp_ajax_load_more_products', 'load_more_products_callback');
add_action('wp_ajax_nopriv_load_more_products', 'load_more_products_callback');

function load_more_products_callback() {
    filter_products_callback();
}
关键说明
  1. 参数同步:全局变量filterParams统一存储所有筛选和分页参数,确保筛选、无限加载的请求参数完全一致。
  2. 状态重置:每次筛选后重置页码为1,更新hasMore状态,避免无限加载从之前的页码继续。
  3. 后端逻辑复用:无限加载的回调直接调用筛选的查询逻辑,减少重复代码,保证两次查询规则一致。
  4. 终止条件:后端返回总页数,前端通过对比当前页码和总页数,判断是否还有更多数据可加载。

内容的提问来源于stack exchange,提问作者libertarian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:43:40