构建第一个页面
在 React 应用中接入 Imposia,把 HTML 渲染成 A4 页面,然后打印或另存为 PDF。
本指南为现有 React 应用添加分页预览。完成后,同一个组件既能把你的 HTML 显示为 A4 页面,又能打开浏览器原生打印流程,输出纸张或 PDF。
开始之前
你需要 React 18 或更高版本,以及客户端浏览器环境。Imposia 不会在 Node.js 或服务端渲染阶段生成页面,请把它挂载在框架的客户端边界之内。
安装 React 包
pnpm add @imposia/react react react-dom在这个组件里或应用的客户端入口文件中导入一次包内样式表。重复导入没有影响,但完全忘记导入会让 Viewer 失去样式。
渲染页面文档
import { ImposiaPageViewer, type ImposiaPageViewerHandle } from "@imposia/react";
import { useRef } from "react";
import "@imposia/react/styles.css";
export function Preview() {
const viewer = useRef<ImposiaPageViewerHandle>(null);
return (
<>
<ImposiaPageViewer
ref={viewer}
source={{ html: "<article><h1>你好</h1><p>浏览器原生页面。</p></article>" }}
documentOptions={{ page: { size: "A4", margin: "18mm" } }}
/>
<button type="button" onClick={() => void viewer.current?.print()}>
打印 / 另存为 PDF
</button>
</>
);
}source.html 提供要分页的内容,documentOptions.page 设置纸张尺寸和页边距。句柄始终指向最近一次成功完成的页面文档——绝不会指向仍在构建中的那份。
确认结果
在浏览器中打开该组件。你的 HTML 应显示为 Viewer 中的一张 A4 页面。
点击打印 / 另存为 PDF。浏览器会为当前显示的页面打开自身的打印对话框,读者在其中选择打印机或另存为 PDF。该方法在对话框发出后即完成;它不返回 PDF 字节。
展示进度与失败
上面的示例渲染的是静态字符串,几乎立即提交。真实的源内容需要时间——图片要稳定,字体要加载,长文档要分成很多页。需要展示这些工作时,请使用 useImposiaDocument。
import { useImposiaDocument } from "@imposia/react";
export function Preview({ html }: { html: string }) {
const { hostRef, state } = useImposiaDocument({ source: { html } });
return (
<>
{state.status === "loading" && <p role="status">正在准备页面…</p>}
{state.status === "error" && <p role="alert">无法为该文档分页。</p>}
<div ref={hostRef} />
</>
);
}state.status 取值为 idle、loading、ready 或 error。首次成功之后,loading 的含义变了:上一批页面仍留在屏幕上,同时下一份文档正在准备,因此加载指示应放在预览旁边,而不是替换预览。state.status 为 error 时,屏幕上显示的仍是最后一次成功的文档。
可选:导出 EPUB
如果产品还需要保留语义、可重排的产物,同一份已提交的文档可以生成 EPUB 3.3 Blob。这是附加输出——它不属于上面的预览与打印路径,可以完全跳过。
元数据是必填项;缺少标题、语言或标识符时,导出会拒绝。
const blob = await viewer.current?.exportEpub({
metadata: { title: "你好", language: "zh-CN", identifier: "urn:example:hello" },
});该方法返回 Blob;把它接入下载或上传是应用自己的事。EPUB 由源内容的语义结构生成,而不是分页后的页面 DOM,因此页面装饰和生成的页码有意不包含在内。