You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在react-to-print中实现PDF导出每页自定义页眉的问题

解决react-to-print导出PDF每页添加自定义页眉的问题

要实现每页自定义页眉,react-to-print本身没有内置配置,但可以通过CSS打印媒体查询 + @page规则来实现,同时先修正你现有代码里的HTML结构错误(这很可能是之前失效的核心原因之一)。

步骤1:修正无效的表格HTML结构

你原来的ManualHeader组件里,tr直接嵌套div和另一个tr不符合HTML规范,表格的tr只能包含td或th,先把结构改对:

const ManualHeader = () => {
  return (
    <>
      <tr>
        <th colSpan="1" className="CatalogSheetProductTitle">
          {currentManualItem?.header || ''}
        </th>
      </tr>
      <tr>
        <th colSpan="1" className="CatalogSheetTitle">
          <span className="sheetCatalogTitle">Instalační manual</span> <br />
          <span className="metel_logo_css">
            METEL<span className="metel_dot">.</span>EU
          </span>
        </th>
      </tr>
    </>
  );
};

步骤2:添加打印专用的CSS样式

在样式文件或组件内的style标签中添加打印媒体查询,用@page规则给页面顶部留出页眉空间,再通过伪元素生成每页固定页眉:

/* 打印专用样式 */
@media print {
  /* 设置页面边距,给页眉预留足够空间 */
  @page {
    margin-top: 4.5cm;
    margin-bottom: 2cm;
  }

  /* 用fixed定位的伪元素生成每页页眉 */
  body::before {
    content: attr(data-print-header);
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 4cm;
    padding: 1cm;
    background: #fff; /* 避免被下方内容穿透覆盖 */
    text-align: center;
    display: flex;
    flex-direction: column;
    justify-content: center;
    border-bottom: 1px solid #ccc;
  }

  /* 隐藏页面内的重复页眉,只保留打印伪元素的页眉 */
  .CatalogSheetProductTitle, .CatalogSheetTitle {
    display: none;
  }
}

步骤3:调整react-to-print的逻辑与配置

因为useReactToPrint返回的打印函数不支持直接传参,所以需要用状态管理当前要打印的手册项,再配合钩子动态设置页眉内容:

// 新增状态保存当前要打印的手册项
const [currentManualItem, setCurrentManualItem] = React.useState(null);
const Manuals = React.useRef();

const handlePrintManual = useReactToPrint({
  content: () => Manuals.current,
  documentTitle: () => `${currentManualItem?.header || 'Manual'}.pdf`,
  copyStyles: true,
  onBeforePrint: () => {
    if (!currentManualItem) return;
    // 动态设置页眉内容到body的自定义属性
    document.body.setAttribute('data-print-header', `
      <div class="CatalogSheetProductTitle">${currentManualItem.header}</div>
      <div class="CatalogSheetTitle">
        <span class="sheetCatalogTitle">Instalační manual</span><br>
        <span class="metel_logo_css">METEL<span class="metel_dot">.</span>EU</span>
      </div>
    `);
  },
  onAfterPrint: () => {
    // 打印完成后清除自定义属性,避免影响正常页面
    document.body.removeAttribute('data-print-header');
  }
});

同时修改点击事件的逻辑:

<a
  key={manualIndex}
  className="hover custom-download"
  onClick={() => {
    setCurrentManualItem(manualItem);
    handlePrintManual();
  }}
>
  <i className="bx bxs-download"></i>{" "}
  {manualItem.header}
</a>

额外注意事项

  • 浏览器打印预览需确保开启“页眉页脚”选项,自定义CSS会覆盖默认页眉样式
  • 如果页眉包含图片,要确保图片路径为绝对路径或已提前加载完成
  • 表格的colSpan值需根据你的实际列数调整,保证页眉占满整行

内容的提问来源于stack exchange,提问作者Matěj Musálek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:52:49