WordPress中Alpine.js AJAX加载更多重复帖子问题求助
问题:WordPress + Alpine.js 加载更多按钮重复加载帖子
使用Alpine.js为WordPress实现帖子AJAX加载功能,分类筛选按钮可正常切换分类并加载对应帖子,但「加载更多」按钮功能异常:点击后加载的是已显示的重复帖子,而非新帖子,无报错信息。
前端代码
<html> <head> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <script> Alpine.data("filterPosts", (adminURL) => ({ posts: "", limit: 6, total: null, category: null, post_type_js: post_id, showDefault: true, showFiltered: false, offset: 0, loadingMore: false, filterPosts(id) { this.showDefault = false; this.showFiltered = true; this.category = id; this.offset = 0; this.fetchPosts(); }, loadMore() { this.loadingMore = true; this.offset += this.limit; this.showFiltered = true; this.fetchPosts(true); }, fetchPosts(append = false) { var formData = new FormData(); formData.append("action", "filterPosts"); formData.append("limit", this.limit); formData.append("post_type_js", this.post_type_js); formData.append("offset", this.offset); if (this.category) { formData.append("category", this.category); } fetch(adminURL, { method: "POST", body: formData, }) .then((res) => res.json()) .then((res) => { if (append) { this.posts = this.posts.concat(res.posts); } else { this.posts = res.posts; } this.loadingMore = false; this.total = res.total; }); }, getTotal() { var formData = new FormData(); formData.append("action", "filterPosts"); fetch(adminURL, { method: "POST", body: formData, }) .then((res) => res.json()) .then((res) => { this.total = res.total; }); }, init() { this.getTotal(); } })); }) </script> </head> <body> <div x-data="filterPosts('<?php echo admin_url('admin-ajax.php'); ?>')"> <section <?php theme_section_attr_id() ?> <?php theme_section_attr_class('main-section js-posts') ?>> <div class="container"> <div class="heading mx-0"> <?php $before_title = get_sub_field('before_title'); if ($before_title) : ?> <strong class="sub-title"><?php echo $before_title ?></strong> <?php endif ?> <?php $title = get_sub_field('title'); if ($title) : ?> <h2><?php echo $title ?> </h2> <?php endif ?> </div> <div class="head js-posts-search-text"> <?php if ($search_value) : ?> <h2 class="h5 fw-semibold"><?php printf(__('Showing results for “%s”', 'base'), $search_value) ?></h2> <?php endif ?> </div> <!--alipne js dynamic post start--> <div class="has-filter row flex-md-row-reverse"> <div class="col-md-8 col-lg-9 js-posts-holder"> <!-- Posts Column --> <div x-show.important="showDefault" class="row cards-area js-posts-items"> <!-- Default posts query --> <?php get_template_part( 'template-parts/posts-filter/default-query' ); ?> </div> <!-- Filtered posts --> <div x-show.important="showFiltered" x-html="posts" class="row cards-area js-posts-items"> </div> <!-- Load More Posts --> <!-- Load More Posts --> <div x-show="total && (posts.split('<!--post-item-->').length -1) < total" @click="loadMore()" class="text-center mt-12 pt-5"> <button :disabled="loadingMore"> <span x-show="!loadingMore">加载更多</span> <span x-show="loadingMore">加载中...</span> </button> </div> </div> <!-- Filtered posts --> <div class="col-md-4 col-lg-3"> <?php get_template_part( 'template-parts/posts-filter/filter-query' ); ?> <!-- Filtered end --> </div> </div> </div> <!--alipne js dynamic post end--> </section> </div> </body> </html>
后端代码
// the ajax function add_action('wp_ajax_filterPosts', 'filterPosts'); add_action('wp_ajax_nopriv_filterPosts', 'filterPosts'); function filterPosts() { $response = [ 'posts' => "", 'total' => 0, ]; // New args for an All Posts Query $all_args = array( 'posts_per_page' => -1, 'post_status' => 'publish', ); $filter_args = array( 'post_status' => 'publish', ); if ($_POST['limit']) { $filter_args['posts_per_page'] = $_POST['limit']; } if ($_POST['offset']) { $filter_args['offset'] = $_POST['offset']; } if ($_POST['post_type_js']) { $filter_args['post_type'] = $_POST['post_type_js']; } if ($_POST['category']) { $filter_args['cat'] = $_POST['category']; $all_args['cat'] = $_POST['category']; } $filter_query = new WP_Query($filter_args); $all_query = new WP_Query($all_args); $response['total'] = $all_query->found_posts; if ($filter_query->have_posts()): while ($filter_query->have_posts()): $filter_query->the_post(); $response['posts'] .= '<!--post-item-->'; $response['posts'] .= load_template_part('/template-parts/posts-filter/single-post'); endwhile; wp_reset_postdata(); endif; echo json_encode($response); die(); } function load_template_part($template_name, $part_name = null, $args = []) { ob_start(); get_template_part($template_name, $part_name, $args); $var = ob_get_contents(); ob_end_clean(); return $var; }
关键修复点说明
- 后端接收offset参数:在
filter_args中添加offset处理,确保WP_Query从指定位置读取帖子,避免重复加载。 - 前端offset增量与limit统一:
loadMore中改为this.offset += this.limit,保证每次加载数量和初始分页一致。 - 完善加载状态与按钮控制:新增
loadingMore变量控制按钮状态,当已加载数量等于总帖子数时自动隐藏按钮。 - 返回总帖子数:后端响应添加
total字段,前端用于判断是否还有更多帖子可加载。
内容的提问来源于stack exchange,提问作者Beep
相关产品推荐
相关产品推荐

