如何深入学习 paged.js 的 ESM 版本和 Hooks?
建议从官方文档、仓库 README 和 Hooks 实例入手,再用一个独立的打印页面练习 ESM 接入。这些资料涵盖了你遇到的两个难点,但不能据此认定存在一套形式与 learneleventy.dev 相同的完整课程。
优先阅读哪些资料?
- 官方文档目录:你已经掌握基础,可以重点阅读“How Paged.js works”,了解分页处理过程,再按需查阅 Generated Content、Named Page 和 Cross References。
- 官方仓库 README:重点阅读“NPM Module”和“Module”。前者展示如何显式调用
Previewer,后者介绍如何注册自定义 Handler。 - Handlers, Hooks and custom javascript:介绍 Hooks 的用途,包括处理打印链接、根据图片比例添加类名等实例。可以先复现一个例子,再改成符合自己需求的版本。
ESM 版本该怎么理解?
ESM 主要改变代码的导入和组织方式。常见的 polyfill 脚本接入方式会自动启动分页;使用模块接口时,可以导入 Previewer,自行决定处理哪些内容、使用哪些样式以及何时开始分页。官方 README 展示了这种调用方式,Previewer API 文档列出了 preview(content, stylesheets, renderTo) 的参数。
还要区分两个“模块”概念:ESM 指 JavaScript 模块机制;paged.js 文档中的功能模块通常由 Handler 组织,通过 Hooks 参与排版。两者有关联,但含义不同。
用最小示例理解 ESM 和 Hooks
这个练习假设你已有能够解析 npm 包并输出浏览器脚本的构建工具。先安装依赖:
npm install pagedjs
在测试页面中准备内容和输出容器:
<template id="print-source">
<article>
<h1>打印测试</h1>
<p>先使用少量内容观察分页过程。</p>
</article>
</template>
<div id="print-output"></div>
浏览器端模块代码如下。其中的 Previewer、Handler 和 registerHandlers 都是官方模块入口导出的接口:
import { Previewer, Handler, registerHandlers } from 'pagedjs';
class InspectPagination extends Handler {
afterParsed(parsed) {
console.log('Headings:', parsed.querySelectorAll('h1').length);
}
afterPageLayout(pageElement) {
console.log('Page laid out:', pageElement);
}
afterRendered(pages) {
console.log('Pagination finished:', pages.length);
}
}
registerHandlers(InspectPagination);
async function renderPrintPreview() {
const source = document.querySelector('#print-source');
const target = document.querySelector('#print-output');
const previewer = new Previewer();
await previewer.preview(
source.content.cloneNode(true),
['/print.css'],
target
);
}
renderPrintPreview().catch(console.error);
创建页面可访问的 /print.css:
@page {
size: A4;
margin: 20mm;
}
h1 {
break-after: avoid;
}
先观察日志,再增加段落,直到内容跨页,对照“内容解析完成”“单页排版完成”和“整份内容分页完成”三个阶段。
import ... from 'pagedjs' 使用的是包名,浏览器通常需要构建工具或 import map 才能解析。11ty 项目中即使安装了 npm 依赖,生成后的页面也不一定能直接解析这个导入语句。上述代码应在浏览器环境运行,并在页面元素就绪后执行。
Hooks 适合做什么?
Hooks 允许你在分页处理的特定阶段执行代码,Handler 则集中定义这些处理方法。可以先掌握三个常用入口:
| Hook | 执行阶段 | 适合的练习 |
|---|---|---|
afterParsed(parsed) | 内容解析后、排版开始前 | 检查标题、为元素添加打印所需的类名 |
afterPageLayout(pageElement, page, breakToken) | 单页排版完成后 | 查看当前页的 DOM,定位分页问题 |
afterRendered(pages) | 所有页面排版完成后 | 统计页数、执行最终检查 |
Hook 方法也可以返回 Promise,让处理流程等待异步任务。具体触发阶段和参数应根据所用版本核对。官方 Hooks 文档解释了这些机制,也说明该页文档仍有待补充。
需要改变内容尺寸或结构的操作,尽量放在排版开始前。分页结束后再插入大段内容或改变字体尺寸,可能让已计算的分页结果失效。
如何接入 11ty 工作流?
建议先让 11ty 从 Markdown 生成一个独立的打印 HTML 页面,再在该页面加载 paged.js 和打印样式。数字花园页面继续使用适合屏幕阅读的模板,两种输出复用内容即可。
学习时可以依次手动调用一次 preview(),注册一个只输出日志的 Handler,再加入一个确实需要的内容处理操作。等这条流程稳定后,再接入 PDF 导出。
分页预览和文件导出也有区别:preview() 负责生成分页结果,不会直接保存 PDF。演示文稿的页面结构和交互需要按目标形式另行设计,不能仅靠这段分页代码完成。
备注:内容仅供参考。
