在制作 WordPress主题时,一个常见需求是“加载更多”功能,通过 AJAX 请求加载更多文章内容。以前写过一篇记录,见下文,本文将根据以前的代码优化使用 Fetch API 实现“加载更多文章”功能。
功能解析
使用 Fetch API 进行 AJAX 请求的基础流程如下:
- 将新文章内容添加到页面。
- 初始化“加载更多”按钮和相关值。
- 用
wp_localize_script
传递服务器路径,安全验证和文字提示。 - 创建下一页数据的 Fetch 请求。
- 通过 PHP 处理 AJAX 请求,并返回成功数据。
一、优化“加载更多”按钮
首先,优化加载按钮,使其可以包含当前分类和页面信息。
<?php
$query = $wp_query->query_vars; // 获取当前页面的查询参数
foreach ( $query as $key => $value ) {
if ( empty( $value ) ) {
unset( $query[ $key ] ); // 移除空参数
}
}
$archive = 'data-archive=' . wp_json_encode( $query ); // 将参数转换为字符串
?>
<div class="post-wrap">
<article>...</article>
<article>...</article>
...
</div>
<button class='btn btn-custom btn-block more-posts' data-current-page="<?php echo get_query_var( 'paged' ) ? esc_attr( get_query_var( 'paged' ) ) : 1; ?>" data-max-page="<?php echo esc_attr( $wp_query->max_num_pages ); ?>" <?php echo esc_attr( $archive ); ?>>加载更多</button>
如果当前页面最大页数大于 1,则显示按钮:
<?php global $wp_query;
if ( $wp_query->max_num_pages > 1): ?>
<button class='btn btn-custom btn-block more-posts' data-page="1">
<?php esc_html_e( 'Load More', 'lerm' ); ?>
</button>
<?php endif;?>
二、传递参数到 JS
使用 wp_localize_script
传递 AJAX 请求相关参数:
function lerm_enqueue_scripts() {
wp_enqueue_script( 'lerm_js', get_stylesheet_directory_uri() . '/assets/js/lerm.js', array(), '2.0', true );
wp_localize_script(
'lerm_js',
'adminajax',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'ajax_nonce' ),
'noposts' => __( 'No older posts found', 'lerm' ),
'loadmore' => __( 'Load more', 'lerm' ),
'loading' => __( 'Loading...', 'lerm' ),
)
);
}
add_action( 'wp_enqueue_scripts', 'lerm_enqueue_scripts' );
三、在 JS 中实现 Fetch API
创建新的 JS 文件,如 lerm.js
:
let loadMorePosts = document.querySelector(".more-posts");
if (loadMorePosts) {
loadMorePosts.addEventListener("click", e => {
e.preventDefault();
loadMorePosts.innerHTML = adminajax.loading;
let params = new URLSearchParams({
action: "lerm_load_more",
security: adminajax.nonce,
...loadMorePosts.dataset,
});
fetch(adminajax.ajaxurl, {
method: "POST",
body: params
})
.then(response => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then(data => {
if (data.success) {
appendPostsToDOM(data.data);
} else {
throw new Error(data.data || 'Unknown error occurred');
}
})
.catch(error => {
console.error('Error:', error);
loadMorePosts.setAttribute('disabled', 'disabled');
loadMorePosts.innerHTML = error.message;
});
});
}
const appendPostsToDOM = (data) => {
const loadMoreBtn = document.querySelector(".more-posts");
const postsList = document.querySelector(".ajax-posts");
if (postsList) {
postsList.insertAdjacentHTML('beforeend', data.content);
}
loadMoreBtn.dataset.currentPage = data.currentPage;
};
四、处理 AJAX 请求的 PHP
在 WordPress 中通过 wp_ajax_
和 wp_ajax_nopriv_
注册处理函数:
function ajax_handle() {
check_ajax_referer( 'ajax_nonce', 'security', true );
$postdata = wp_unslash( $_POST );
if ( ! isset( $postdata['archive'], $postdata['currentPage'] ) ) {
wp_send_json_error( __( 'Invalid request data', 'lerm' ) );
}
$query_args = json_decode( stripslashes( $postdata['archive'] ), true );
if ( ! is_array( $query_args ) ) {
wp_send_json_error( __( 'Invalid query parameters', 'lerm' ) );
}
$query_args = array_merge(
$query_args,
array(
'post_type' => 'post',
'posts_per_page' => 10,
'paged' => (int) $postdata['currentPage'] + 1,
'post_status' => 'publish',
)
);
$posts = new WP_Query( $query_args );
if ( ! $posts->have_posts() || $query_args['paged'] > $posts->max_num_pages ) {
wp_send_json_error( __( 'No more posts!', 'lerm' ) );
}
ob_start();
while ( $posts->have_posts() ) :
$posts->the_post();
get_template_part( 'template-parts/content/content', get_post_format() );
endwhile;
wp_reset_postdata();
$content = ob_get_clean();
wp_send_json_success(
array(
'content' => $content,
'maxPage' => $posts->max_num_pages,
'currentPage' => $query_args['paged'],
'nextPage' => $query_args['paged'] + 1,
'hasMore' => $query_args['paged'] < $posts->max_num_pages,
)
);
}
add_action( 'wp_ajax_lerm_load_more', 'ajax_handle' );
add_action( 'wp_ajax_nopriv_lerm_load_more', 'ajax_handle' );
主要优化点
- 在加载更多文章按钮动态处理
current-page
,当前页面query_vars
。 - 使用
unset
移除了$wp_query->query_vars
查询后的空参数,可有效减少字符串长度。 - 使用
...loadMorePosts.dataset
处理传递的参数,更加简单有效。 - 在后台处理
paged
页面参数,传递数据和文章数据同步。
搜索页面有bug 将第一段代码的if ( empty( $value ))修改成if ( empty( $value ) || ! is_scalar( $value ) )就可以