搜索全站
插件 14 分钟阅读

WordPress 分页插件 WP-PageNavi 与主题分页改造:数字分页替换上一页下一页

首页只有「上一页/下一页」会把深层文章推到收录盲区。本文详解 WP-PageNavi 配置、主题模板替换、WordPress 原生 paginate_links() 自定义分页,以及 rel=next/prev 与 View All 的分页 SEO 取舍。

U
UFO_PF 2026-01-29 · 阅读 14 分钟
Wo 插件
阅读提示
本文约 5,400 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:收录 200 篇,实际 400 篇,差在哪

一个典型的国内博客现象:发布量一直在涨,百度资源平台和 Google Search Console 里的”已编入索引”却卡在某个数字不动。排除掉内容质量问题后,最常见的结构性原因是分页链路断了。

默认主题(Twenty Twenty-Four 等)在列表页底部只输出 « 较早的文章 / 较新的文章 » 两个链接。Googlebot 从首页出发,每到一个列表页只能往下走一层,走到第十层基本就放弃。更麻烦的是归档页 /page/2/ 之后几乎没有内链支持,权重衰竭,深层文章如同埋在地下。数字分页把 1、2、3…N 全部铺出来,等于给每一层都追加了入口;同时在「第 3 页」Articles 里的大量深层次页面也能被重新发现。

实现方式两类:装 WP-PageNavi(作者 Lester ‘GaMerZ’ Chan,wordpress.org 安装量 80 万+,末尾虽多年未大更新但兼容性一直很好),或者用 WordPress 内置的 paginate_links() 自己画。后者更干净,没有多余 CSS/JS。

原理分析:分页函数的三种实现路径

方案 函数/调用 依赖 灵活性
主题默认 the_posts_pagination() / posts_nav_link() 无 低,只能改 prev_text/next_text
WP-PageNavi wp_pagenavi() 模板标签 插件 + 自带 CSS 中,后台可调页数、省略号、端点
原生 paginate_links() paginate_links( $args ) 无 高,base/format/add_args 全开放

三者的底层都一样:读取 $GLOBALS['wp_query']->max_num_pages 这个总页数,再结合当前 paged 变量算偏移。所以不管用哪个,只要最终输出的 HTML 里保留了 href="/page/3/" 这样的真实链接,对收录的提升效果就是等价的。

需要注意 WordPress 的 paginate_links() 有个历史行为:base 默认会用到 %_% 和 %#% 两个占位符,配合 format 生成。如果你的站点开了 /%category%/%postname%/ 之外的自定义 permalink 结构,base 必须手写,否则会生成 /page/3/?s=xxx 这种混搭 URL。

另一条容易被忽略的线:分页 SEO。Google 早在 2019 年就宣布不再使用 rel="next"/rel="prev" 作为索引信号,但它仍然是有效的 HTML 提示;更重要的是不要把 /page/2/ 之后的页面 noindex,那样深层文章就彻底失去了进入索引的跳板——正确做法是正常 index,并用 rel=canonical 自指向(不要让第二页 canonical 指向首页,那会直接把自己从索引里划掉)。

保姆级实操

步骤 1:安装并接入 WP-PageNavi

后台装好后,找到主题的分页输出位置。Twenty 系列主题在 template-parts/content.php 之后、index.php 里:

// 找到类似这行,注释或替换掉
// the_posts_navigation();

// 换成 WP-PageNavi
if ( function_exists( 'wp_pagenavi' ) ) {
    wp_pagenavi();
} else {
    the_posts_navigation(); // 保留兜底,避免插件停用后前台崩
}

子主题改造务必用 remove_action / 覆写模板,不要直接改父主题文件。

步骤 2:后台基参

「设置 → PageNavi」里建议:

  • Number of pages to show:10(不要设 0/All,深层列表会生成上百个 <a>)
  • Show “Page X of Y”:关闭,中文站信息冗余
  • Style:选 Classic,别选 Drop-down List(下拉对爬虫不可见,且对用户不友好)
  • 如果想套自定义 CSS,把「Use pagenavi-css.css」关掉,自己写样式

步骤 3:不装插件,用原生 paginate_links()

下面这段是我在多数站点上直接用的版本,支持中文文案、保留 query 参数(比如搜索页的 ?s=):

function mf_numeric_pagination( $wp_query = null ) {
    if ( null === $wp_query ) {
        global $wp_query;
    }
    $total = (int) $wp_query->max_num_pages;
    if ( $total <= 1 ) {
        return;
    }
    $current = max( 1, get_query_var( 'paged' ) ? (int) get_query_var( 'paged' ) : 1 );

    $links = paginate_links( array(
        'base'      => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
        'format'    => '?paged=%#%',
        'current'   => $current,
        'total'     => $total,
        'mid_size'  => 2,
        'end_size'  => 1,
        'prev_text' => '&laquo; 上一页',
        'next_text' => '下一页 &raquo;',
        'type'      => 'list',
    ) );
    // 搜索页要把 s 参数带上
    if ( is_search() ) {
        $links = str_replace( '/page/', '/page/', $links );
    }
    echo '<nav class="mf-pagination" role="navigation" aria-label="分页导航">' . $links . '</nav>';
}

搜索结果页尤其要注意:paginate_links() 默认会丢掉 ?s=关键词,必须补上:

add_filter( 'paginate_links', function( $link ) {
    if ( is_search() && ! empty( $_GET['s'] ) ) {
        $link = add_query_arg( 's', rawurlencode( wp_unslash( $_GET['s'] ) ), $link );
    }
    return $link;
} );

步骤 4:替换到指定模板

// archive.php / index.php / search.php 里循环结束之后
mf_numeric_pagination();

WooCommerce 商店页的分页不用改,WC 自带 woocommerce_pagination() 输出的就是同样的结构,改 CSS 即可。

步骤 5:配套 CSS

.mf-pagination ul.page-numbers {
    display: flex; flex-wrap: wrap; gap: 6px;
    list-style: none; padding: 0; margin: 28px 0;
}
.mf-pagination li { margin: 0; }
.mf-pagination a,
.mf-pagination span {
    display: inline-block; min-width: 34px; padding: 7px 11px;
    border: 1px solid #e5e7eb; border-radius: 6px;
    color: #374151; text-align: center; line-height: 1.2;
    font-size: 14px; text-decoration: none;
}
.mf-pagination a:hover { border-color: #c0392b; color: #c0392b; }
.mf-pagination span.current {
    background: #c0392b; border-color: #c0392b; color: #fff; font-weight: 600;
}
.mf-pagination .next, .mf-pagination .prev { border-color: transparent; }

步骤 6:验证输出

进任意归档页第 2 页,查看源码确认 <nav class="mf-pagination"> 里包含 href=".../page/3/" 真实链接(不是 javascript:void(0)),确认 <span class="current">2</span> 出现一次。

常见踩坑

  1. max_num_pages 恒等于 1:静态首页用自定义 WP_Query 时忘了传 paged,正确写法是 'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1。这是分页失效的第一大原因。
  2. 首页分页 404:静态首页(Reading Settings 里设了 Front page)要用 get_query_var( 'page' ) 而不是 'paged',两者变量不同。
  3. 案例:某小说站改造后用 query_posts() 重查了一遍再输出 WP-PageNavi,结果无论点第几页都显示同样内容。原因:query_posts() 会覆盖主查询,而 wp_pagenavi() 仍读的是被污染后的 $wp_query。改用 pre_get_posts 钩子改写主查询才彻底解决——这个错踩了整整两周。
  4. 分页链接带了 ?s= 后 cyrillic 乱码:用 rawurlencode() 处理搜索词,并在 paginate_links 里不要再 esc_html 一次链接。
  5. 插件 CSS 未加载:某些主题住了 wp_head(),或者在 functions.php 里 deregister 了 wp-pagenavi 的 style 句柄(句柄名就叫 wp-pagenavi)。回滚 deregister 或者自己写 CSS。
  6. paged 在 pretty permalink 下取不到:确保 get_pagenum_link() 能正常生成 /page/2/ 形式;如果站点用了 %post_id%.html 这种后缀式固定链接,/page/2/ 会与被 RewriteRule 冲突,需要调整 rewrite 优先级。
  7. 把 /page/2/ 设成了 canonical 到首页:这是自杀式操作,会让第 2 页之后全部从索引消失。Yoast/Rank Math 默认不会这么做,但自己写 <link rel=canonical> 时极容易写错。

延伸阅读:WordPress 分页与收录策略、WordPress 主题模板结构

总结

三条判断标准:第一,能不能看到真实 href——javascript: 或 AJAX 分页对收录毫无帮助;第二,paged / page 变量是否取对——自定义 WP_Query 场景必查;第三,是否 canonical 自指向——分页页的正确 canonical 是它自己。至于插件还是代码:WP-PageNavi 胜在零代码接入、后台直观,适合新手站;paginate_links() 胜在零依赖、便于自定义结构和 add_query_arg 扩展,适合已有开发能力的站点。两者没有性能差异,因为瓶颈从来不在分页渲染上。

相关处理:WordPress 缓存与动态内容冲突排查

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。