
本教程旨在指导开发者如何利用 paged.js 库为可打印的 HTML 文档动态生成一个结构清晰的目录。文章将详细介绍如何通过 JavaScript 遍历文档中的标题元素、生成锚点链接,并将其集成到 paged.js 的处理流程中,从而在打印输出时实现一个功能完善、自动更新的目录,无需直接通过 JavaScript 获取页面号。
在构建可打印的 HTML 文档时,尤其对于长篇内容,一个带有章节页码的目录是必不可少的。传统的做法可能涉及在 JavaScript 中尝试获取特定元素所在的页码,但由于页码是打印布局的产物,并非 DOM 元素的固有属性,这种方法往往难以实现。paged.js 提供了一种优雅的解决方案,允许我们在其渲染流程中动态构建目录,从而间接实现页码关联的效果。
paged.js 的核心在于将 HTML 内容流式地分页,并应用 CSS 打印样式。为了生成动态目录,我们不需要直接在 JavaScript 中计算页码。相反,我们可以在 paged.js 开始分页之前,通过 JavaScript 遍历文档中的所有章节标题,为它们创建唯一的 ID,并在目录区域生成指向这些 ID 的锚点链接。当 paged.js 完成分页并生成打印输出时,这些锚点链接将自然地指向其对应的章节起始位置,而打印机或 PDF 阅读器则会显示这些章节所在的实际页码。
paged.js 提供了处理程序(Handlers)机制,允许我们在其处理生命周期的不同阶段注入自定义逻辑。对于目录生成,beforeParsed 钩子是理想的选择,因为它在 HTML 内容被解析但尚未进行分页布局之前执行。
立即学习“前端免费学习笔记(深入)”;
首先,确保您的 HTML 文档包含清晰的章节标题和目录的占位符。
示例 HTML 结构:
<!DOCTYPE html>
<html>
<head>
<title>可打印文档</title>
<!-- 引入 paged.js -->
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<!-- 您的自定义脚本和样式将在此处 -->
</head>
<body>
<!-- 目录占位符 -->
<div id="my-toc-content">
<h2>目录</h2>
<ul id="list-toc-generated">
<!-- 目录项将在此处动态生成 -->
</ul>
</div>
<!-- 文档内容 -->
<h1 id="pre-digital_era" class="title-element" data-title-level="h1">
数字时代前夕
</h1>
<p>这是数字时代前夕的相关内容...</p>
<h2 id="early_computers">早期计算机</h2>
<p>早期计算机的发展历史...</p>
<h1 id="digital_era" class="title-element" data-title-level="h1">
数字时代
</h1>
<p>这是数字时代的相关内容...</p>
<h2 id="internet_revolution">互联网革命</h2>
<p>互联网如何改变世界...</p>
</body>
</html>接下来,我们将编写一个 JavaScript 函数来遍历文档中的标题,并根据它们生成目录项。
/**
* 动态生成目录
* @param {object} config - 配置对象
* @param {HTMLElement} config.content - 文档内容根元素
* @param {string} config.tocElement - 目录容器的选择器
* @param {string[]} config.titleElements - 标题元素的选择器数组,按层级顺序
*/
function createToc(config) {
const content = config.content; // 文档内容根元素
const tocElementSelector = config.tocElement; // 目录容器选择器
const titleElementsSelectors = config.titleElements; // 标题元素选择器数组
// 查找目录容器,并创建或获取 ul 元素
let tocContainer = content.querySelector(tocElementSelector);
if (!tocContainer) {
console.warn(`目录容器 ${tocElementSelector} 未找到.`);
return;
}
let tocUl = tocContainer.querySelector("#list-toc-generated");
if (!tocUl) {
tocUl = document.createElement("ul");
tocUl.id = "list-toc-generated";
tocContainer.appendChild(tocUl);
} else {
// 清空现有目录,防止重复生成
tocUl.innerHTML = '';
}
let tocElementNbr = 0; // 用于生成唯一 ID 的计数器
// 1. 遍历所有标题元素,添加必要属性
for (let i = 0; i < titleElementsSelectors.length; i++) {
let titleHierarchy = i + 1; // 标题层级 (1, 2, 3...)
let currentLevelTitles = content.querySelectorAll(titleElementsSelectors[i]);
currentLevelTitles.forEach(function (element) {
// 添加通用类名和层级数据属性
element.classList.add("title-element");
element.setAttribute("data-title-level", titleHierarchy);
// 如果没有 ID,则生成一个唯一 ID
if (element.id === "") {
tocElementNbr++;
element.id = `title-element-${tocElementNbr}`;
}
});
}
// 2. 遍历所有标记为 "title-element" 的元素,创建目录列表项
let tocElements = content.querySelectorAll(".title-element");
for (let i = 0; i < tocElements.length; i++) {
let tocElement = tocElements[i];
let tocNewLi = document.createElement("li");
// 添加目录项的层级类名
tocNewLi.classList.add("toc-element");
tocNewLi.classList.add(`toc-element-level-${tocElement.dataset.titleLevel}`);
// 复制标题元素的其他类名到目录项(可选,用于样式继承)
let classTocElement = tocElement.classList;
for (let n = 0; n < classTocElement.length; n++) {
if (classTocElement[n] !== "title-element") { // 避免复制内部使用的类名
tocNewLi.classList.add(classTocElement[n]);
}
}
// 创建锚点链接
tocNewLi.innerHTML = `<a href="#${tocElement.id}">${tocElement.innerHTML}</a>`;
tocUl.appendChild(tocNewLi);
}
}代码解释:
为了让 createToc 函数在 paged.js 处理文档时自动执行,我们需要创建一个 Paged.Handler 并将其注册到 paged.js。
将以下代码添加到您的 HTML 文档的 <head> 部分,紧随 paged.js 脚本之后:
<script>
// 确保 createToc 函数已定义
// (您可以将 createToc 函数放在这里,或者确保它在全局作用域中可用)
class CustomTocHandler extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}
// beforeParsed 钩子在 HTML 内容被解析但尚未进行分页布局之前执行
beforeParsed(content) {
// 调用 createToc 函数,传入配置
createToc({
content: content, // paged.js 提供的文档内容根元素
tocElement: "#my-toc-content", // 您的目录容器 ID
titleElements: ["h1", "h2", "h3"], // 您希望作为目录项的标题选择器数组
// 例如: [".mw-content-ltr h2", "h3"]
});
}
}
// 注册您的自定义处理程序
Paged.registerHandlers(CustomTocHandler);
</script>代码解释:
#my-toc-content ul {
list-style: none;
padding-left: 0;
}
.toc-element-level-1 {
margin-left: 0;
font-weight: bold;
}
.toc-element-level-2 {
margin-left: 20px;
}
.toc-element-level-3 {
margin-left: 40px;
font-style: italic;
}
/* 您也可以使用 CSS counters 来添加页码,paged.js 会自动处理 */
/* 例如,在 @page 规则中设置页码 */
@page {
@bottom-right {
content: counter(page);
}
}通过 paged.js 的处理程序机制,我们可以优雅地解决为可打印 HTML 文档动态生成目录的问题。这种方法避免了在 JavaScript 中复杂地计算页码,而是利用了 paged.js 在分页前对 DOM 进行操作的能力,通过锚点链接实现了目录与章节的关联。结合适当的 CSS 样式,您可以为您的打印输出提供一个专业、功能完善且易于导航的动态目录。
以上就是使用 paged.js 高效构建可打印HTML的动态目录的详细内容,更多请关注php中文网其它相关文章!
HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号