- 后端 PHP:修改或创建一个专门用于返回分页内容的接口。
- 前端 HTML:调整页面结构,准备好 AJAX 加载的目标区域。
- 前端 JavaScript:编写 AJAX 逻辑,监听分页点击事件,并动态更新页面内容。
下面我将提供一个详细的、可操作的步骤和代码示例。

核心思路
- 分离逻辑:将“获取列表数据”和“生成分页条”这两个功能分开,传统的
arc.listview.class.php会同时处理这两件事,我们需要一个只负责返回数据(不带分页条)的 PHP 接口。 - 前端接管:用 JavaScript 监听分页链接的点击事件,阻止其默认的页面跳转行为。
- AJAX 请求:点击后,通过 AJAX 向后端接口请求指定页的数据。
- 动态渲染:后端返回纯 HTML 内容(列表部分),前端 JavaScript 接收到后,用这些内容替换掉页面上的旧列表,并更新分页条。
第一步:后端 PHP 修改(创建 AJAX 接口)
这是最关键的一步,我们需要创建一个新的 PHP 文件来处理 AJAX 请求,或者修改现有的列表页面文件。
方案 A:推荐 - 创建一个独立的 AJAX 接口文件(更清晰)
-
复制列表模板文件 在你的
/templets/目录下,找到你正在使用的列表模板文件,list_article.htm,将其复制一份,命名为list_ajax.htm。-
重要:在
list_ajax.htm中,只保留列表循环部分的 HTML 代码,删除掉所有与分页相关的代码(如{dede:pagelist}和{dede:pagebreak})以及页头页尾。 -
你的
list_article.htm可能有这样的结构:
(图片来源网络,侵删)<!DOCTYPE html> <html> <head> <title>{dede:field.title/}</title> <!-- ... 其他 head 内容 ... --> </head> <body> <div class="main"> <!-- 这是列表部分 --> <ul class="article-list"> {dede:list pagesize='10'} <li> <a href="[field:arcurl/]">[field:title/]</a> <span>[field:pubdate function="MyDate('Y-m-d', @me)"/]</span> </li> {/dede:list} </ul> <!-- 这是分页部分,需要删除 --> <div class="dede_pages"> <ul> {dede:pagelist listsize='4' listitem='info,index,end,pre,next,pageno'} ... {/dede:list} </ul> </div> </div> <!-- ... 页脚等 ... --> </body> </html> -
你的
list_ajax.htm就应该简化为:<!-- list_ajax.htm --> <ul class="article-list"> {dede:list pagesize='10'} <li> <a href="[field:arcurl/]">[field:title/]</a> <span>[field:pubdate function="MyDate('Y-m-d', @me)"/]</span> </li> {/dede:list} </ul>这个文件现在只负责生成列表的 HTML 片段。
-
-
创建 AJAX 处理 PHP 文件 在你的网站根目录下(或者
plus/目录),创建一个新文件,ajax_list.php。<?php /** * DedeCMS AJAX 列表接口 * 用法: /ajax_list.php?tid=栏目ID&page=页码 */ // 引入 DedeCMS 核心文件 require_once (dirname(__FILE__) . "/include/common.inc.php"); require_once DEDEINC."/arc.listview.class.php"; // 获取 AJAX 传过来的参数 $tid = isset($tid) && is_numeric($tid) ? $tid : 0; $page = isset($page) && is_numeric($page) ? intval($page) : 1; if ($tid == 0) { exit('Error: Invalid Category ID.'); } // 实例化列表类 $lv = new ListView($tid); // 设置每页显示条数 (可以和模板中保持一致) $lv->PageSize = 10; // 设置当前页码 $lv->SetPage($page); // 获取并输出列表内容 (这里会自动使用 list_ajax.htm 模板) // 注意:这里我们只需要获取列表内容,不需要获取分页条 $listHtml = $lv->GetListHtml(); // 直接输出列表 HTML echo $listHtml; // 结束脚本,防止其他输出 exit(); ?>
方案 B:修改现有列表页面(不推荐,但可行)
直接修改 arc.listview.class.php 文件,判断如果是 AJAX 请求,则只返回列表内容,这种方法会修改核心文件,不利于后期升级,所以不推荐新手使用。

第二步:前端 HTML 修改(准备容器)
你需要修改原始的列表模板文件 list_article.htm。
-
添加一个容器 给你的列表部分包裹一个
div,并给它一个唯一的id,这样 JavaScript 就能方便地找到它并更新内容。<!-- list_article.htm --> <!DOCTYPE html> <html> <head> <title>{dede:field.title/}</title> <!-- 引入 jQuery 库 --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <div class="main"> <!-- 1. 为列表内容添加一个容器 --> <div id="ajax-list-container"> <!-- 原始的列表循环将由 PHP 后端填充 --> {dede:list pagesize='10'} <li> <a href="[field:arcurl/]">[field:title/]</a> <span>[field:pubdate function="MyDate('Y-m-d', @me)"/]</span> </li> {/dede:list} </div> <!-- 2. 保留分页条,但需要给它一个 ID 并修改链接 --> <div class="dede_pages" id="pagination"> <ul> {dede:pagelist listsize='4' listitem='info,index,end,pre,next,pageno'} <!-- 默认生成的链接类似 /plus/list.php?tid=1&PageNo=2 --> <!-- 我们需要通过 JS 来处理,所以先保持原样 --> <li><a href="[field:link/]">[field:text/]</a></li> {/dede:pagelist} </ul> </div> </div> <!-- 3. 在底部添加你的 JavaScript 代码 --> <script> $(document).ready(function() { // 监听分页点击事件 $(document).on('click', '#pagination a', function(e) { // 阻止默认的页面跳转行为 e.preventDefault(); // 获取点击的链接地址 var url = $(this).attr('href'); // 从链接中解析出页码 tid 和 page // /plus/list.php?tid=1&PageNo=2 var regex = /[?&]tid=(\d+)/; var tidMatch = url.match(regex); var regexPage = /[?&]PageNo=(\d+)/; var pageMatch = url.match(regexPage); if (!tidMatch || !pageMatch) { alert('无法解析分页参数'); return; } var tid = tidMatch[1]; var page = pageMatch[1]; // 显示一个加载提示(可选) $('#ajax-list-container').html('<p>加载中...</p>'); // 发起 AJAX 请求 $.ajax({ type: 'GET', url: '/ajax_list.php', // 我们第一步创建的接口文件 data: { tid: tid, page: page }, dataType: 'html', // 期望返回的数据类型是 HTML success: function(response) { // 请求成功,用返回的 HTML 更新列表容器 $('#ajax-list-container').html(response); // (可选) 更新浏览器地址栏的 URL,使前进/后退按钮可用 // window.history.pushState(null, '', url); // (可选) 滚动到页面顶部 // $('html, body').animate({scrollTop: 0}, 'fast'); }, error: function(xhr, status, error) { // 请求失败,显示错误信息 $('#ajax-list-container').html('<p>加载失败,请刷新页面重试。</p>'); console.error("AJAX Error:", status, error); } }); }); }); </script> </body> </html>
第三步:优化与注意事项
-
URL 美化与 History API 上面代码中注释掉了
window.history.pushState,加上这行代码后,AJAX 加载的页面 URL 也会真实地变化到浏览器地址栏,这样用户就可以使用浏览器的前进/后退按钮了,这是一个很好的用户体验优化。 -
SEO 考虑 AJAX 分页对 SEO 有一定影响,因为搜索引擎爬虫可能无法很好地执行 JavaScript,对于内容非常重要的列表页面(如文章列表),建议:
- 保留传统分页:确保搜索引擎能抓取到所有页面。
- 对 AJAX 分页进行“优雅降级”:即默认情况下还是传统分页,当用户浏览器启用 JavaScript 后,再切换到 AJAX 分页模式,上面的代码已经实现了这一点,对搜索引擎来说,它看到的还是完整的、带分页的页面。
-
错误处理 在 AJAX 的
error回调函数中,我们提供了一个友好的错误提示,这比让用户看到一个空白页面要好得多。 -
加载状态 在 AJAX 请求开始时,显示一个“加载中...”的提示,可以给用户明确的反馈,提升交互体验。
-
jQuery 示例中使用了 jQuery,因为它极大地简化了 DOM 操作和 AJAX 请求,如果你的项目不使用 jQuery,你需要用原生的 JavaScript
XMLHttpRequest或fetchAPI 来实现同样的功能,代码会稍微复杂一些。
通过以上三个步骤,你就成功地将 DedeCMS 的传统分页改为了无刷新的 AJAX 分页。
- 后端 (
ajax_list.php):负责根据请求返回纯 HTML 列表片段。 - 前端 (
list_article.htm):提供容器和分页条,并包含处理 AJAX 请求的 JavaScript 逻辑。 - 模板 (
list_ajax.htm):一个精简的、只负责生成列表的模板文件。
这个方案结构清晰,易于维护,并且是业界处理此类问题的标准做法。
