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
相关产品推荐
相关产品推荐

