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

Timber是否原生支持实现带筛选搜索分页的同页加载列表组件

Timber 没有提供整套 AJAX 筛选、分页、搜索的开箱原生实现,但它的模板分离机制可以彻底解决你当前代码里 PHP 拼接 HTML 结构混乱、逻辑和视图耦合的问题,整体实现会比你现在的写法整洁非常多,具体实现方式如下:

核心改造点

你当前代码混乱的核心原因是在 PHP 逻辑中直接拼接 HTML 字符串,还残留了dump()、die()调试代码,以及ob_get_clean()未对应开启输出缓冲的逻辑bug。用 Timber 改造后,所有视图层逻辑全部放到 Twig 模板中,PHP 只负责处理数据查询、参数接收,完全分离逻辑和视图。


具体实现代码

1. PHP 层逻辑(主题 functions.php 中添加)

首先替换掉原来硬写在wp_head里的 ajaxurl 输出,改用官方推荐的脚本注入方式传递参数,AJAX 处理函数不再拼接 HTML,直接调用 Timber 渲染模板返回内容:

// 前端脚本注入AJAX地址
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('ft-custom-script', get_stylesheet_directory_uri() . '/assets/js/ft-filter.js', ['jquery'], '1.0', true);
    wp_localize_script('ft-custom-script', 'ftConfig', [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'defaultPerPage' => 4
    ]);
});

// AJAX请求处理
add_action('wp_ajax_flatsome_get_posts', 'flatsome_get_posts');
add_action('wp_ajax_nopriv_flatsome_get_posts', 'flatsome_get_posts');
function flatsome_get_posts() {
    // 接收前端参数
    $paged = intval($_GET['paged'] ?? 1);
    $perPage = intval($_GET['per_page'] ?? 4);
    $category = sanitize_text_field($_GET['category'] ?? '');
    $keyword = sanitize_text_field($_GET['keyword'] ?? '');

    // 组装查询参数
    $args = [
        'post_type'      => 'books',
        'paged'          => max(1, $paged),
        'posts_per_page' => max(1, $perPage),
        'post_status'    => 'publish'
    ];

    // 分类筛选参数
    if (!empty($category)) {
        $args['tax_query'] = [
            [
                'taxonomy' => 'category', // 替换成你实际用的分类法slug
                'field'    => 'slug',
                'terms'    => $category
            ]
        ];
    }

    // 关键词搜索参数
    if (!empty($keyword)) {
        $args['s'] = $keyword;
    }

    $query = new Timber\PostQuery($args);

    // 用Timber渲染Twig模板,替代原来的字符串拼接
    $postsHtml = Timber::compile('partials/ft-post-list.twig', [
        'posts' => $query->get_posts()
    ]);

    wp_send_json_success([
        'posts' => $postsHtml,
        'pages' => $query->pagination('total-pages'),
    ]);
    exit;
}

2. Twig 模板文件

主组件模板(放到页面引用的Twig文件中)

<div class="ft-block">
    <div class="ft-block__header">
        <label for="ft-category">分类筛选</label>
        <select name="category" id="ft-category">
            <option value="" selected>全部分类</option>
            <option value="books">图书</option>
            <option value="podcast">播客</option>
        </select>

        <label>
            <input type="search" name="ft-keyword" placeholder="输入关键词搜索">
            <button id="ft-do-search">搜索</button>
        </label>

        {# 需求要求的单页展示数量选择器 #}
        <label for="ft-per-page">每页显示</label>
        <select name="per_page" id="ft-per-page">
            <option value="4" selected>4条</option>
            <option value="8">8条</option>
            <option value="12">12条</option>
            <option value="20">20条</option>
        </select>
    </div>

    <div id="ft-block__posts-holder">
        {# 初始页面加载时直接渲染第一页内容,不用等JS加载完再请求 #}
        {% include 'partials/ft-post-list.twig' with {
            posts: Timber::get_posts({
                post_type: 'books',
                posts_per_page: 4,
                paged: 1
            })
        } %}
    </div>

    <div class="ft-block__footer">
        <div id="ft-block__pager"></div>
    </div>
</div>

列表项渲染模板(新建 partials/ft-post-list.twig)

{% if posts is not empty %}
    {% for post in posts %}
        <div class="ft_post">
            <div class="ft-post__image">
                {% if post.thumbnail %}
                    <img src="{{ post.thumbnail.src('full') }}" alt="{{ post.title }}">
                {% endif %}
            </div>
            <h3 class="ft-post__title" style="white-space:normal;">
                {{ post.title }}
            </h3>
            <p>{{ post.content|striptags|trim }}</p>
        </div>
    {% endfor %}
{% else %}
    <div class="ft-no-result">没有找到符合条件的内容</div>
{% endif %}

3. JS 逻辑优化(assets/js/ft-filter.js)

修复原有代码重复初始化分页插件导致事件多次绑定的bug,新增每页数量切换、回车触发搜索的逻辑:

jQuery(document).ready(function ($) {
    let currentPage = 1;
    const $postsHolder = $('#ft-block__posts-holder');
    const $pager = $('#ft-block__pager');
    const $categorySelect = $('#ft-category');
    const $searchInput = $('input[name=ft-keyword]');
    const $searchBtn = $('#ft-do-search');
    const $perPageSelect = $('#ft-per-page');

    function ftGetPost(page = 1) {
        currentPage = page;
        $.ajax({
            type: 'GET',
            url: ftConfig.ajaxUrl,
            dataType: 'JSON',
            data: {
                'action': 'flatsome_get_posts',
                'paged': page,
                'per_page': $perPageSelect.val(),
                'category': $categorySelect.val(),
                'keyword': $searchInput.val().trim(),
            },
            beforeSend: function () {
                $postsHolder.addClass('loading');
            },
            success: function (res) {
                if (!res.success) return;
                $postsHolder.html(res.data.posts);
                // 先销毁已有的分页实例,避免重复绑定
                $pager.twbsPagination('destroy');
                $pager.twbsPagination({
                    totalPages: res.data.pages || 1,
                    startPage: page,
                    visiblePages: 7,
                    onPageClick: function (event, pageNum) {
                        if (pageNum !== currentPage) {
                            ftGetPost(pageNum);
                        }
                    }
                });
            },
            complete: function () {
                $postsHolder.removeClass('loading');
            }
        });
    }

    // 初始化加载
    ftGetPost();

    // 分类、每页数量切换时重置到第一页刷新
    $categorySelect.add($perPageSelect).change(function () {
        ftGetPost(1);
    });

    // 搜索:点击按钮、输入框回车都触发
    $searchBtn.click(function () {
        ftGetPost(1);
    });
    $searchInput.on('keydown', function (e) {
        if (e.keyCode === 13) {
            e.preventDefault();
            ftGetPost(1);
        }
    });
});
改造后优势
  • 没有任何PHP拼接HTML的混乱代码,所有视图层结构都在Twig文件中,修改样式、调整结构不需要改PHP逻辑
  • 初始加载直接渲染第一页内容,不需要等JS执行完再发AJAX请求,首屏加载更快
  • 修复了原有代码的调试残留、输出缓冲bug、分页重复初始化的问题
  • 完整覆盖需求里提到的分类筛选、搜索、分页、单页数量选择功能,搜索结果直接在当前页展示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:39:19