网页打印指定DOM元素的区域

适用场景

  • 打印表格、订单、报告(只打印关键内容,不打印导航栏、页脚等)。

  • 打印模态框内容(如弹窗里的数据)。

  • 自定义打印样式(通过 includeGlobalStyles: false 完全控制打印样式)。

封装通用函数

/**
 * 打印指定ID元素的内容
 * @param {string} elementId - 要打印的DOM元素ID
 * @param {Object} [options] - 可选配置
 * @param {string} [options.title="打印"] - 打印页面的标题
 * @param {boolean} [options.includeGlobalStyles=true] - 是否包含原页面的全局样式
 * @param {Function} [options.beforePrint] - 打印前的回调
 * @param {Function} [options.afterPrint] - 打印后的回调
 */
function printElement(elementId, options = {}) {
  const {
    title = "打印",
    includeGlobalStyles = true,
    beforePrint,
    afterPrint,
  } = options;

  const elementToPrint = document.getElementById(elementId);
  if (!elementToPrint) {
    console.error(`Element with ID "${elementId}" not found.`);
    return;
  }

  // 创建隐藏的 iframe
  const iframe = document.createElement("iframe");
  iframe.style.position = "absolute";
  iframe.style.width = "0";
  iframe.style.height = "0";
  iframe.style.border = "0";
  iframe.style.overflow = "hidden";

  // 复制原元素的HTML和样式
  iframe.onload = () => {
    try {
      const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
      iframeDoc.open();
      
      // 获取原页面的全局样式(可选)
      const globalStyles = includeGlobalStyles
        ? Array.from(document.querySelectorAll("style, link[rel='stylesheet']"))
            .map((el) => el.outerHTML)
            .join("\n")
        : "";

      iframeDoc.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>${title}</title>
            ${globalStyles}
            <style>
              @page { margin: 0; }
              body { margin: 0.5cm; }
            </style>
          </head>
          <body>
            ${elementToPrint.outerHTML}
          </body>
        </html>
      `);
      iframeDoc.close();

      // 打印前回调
      if (typeof beforePrint === "function") beforePrint(iframe);

      // 触发打印
      setTimeout(() => {
        iframe.contentWindow.focus();
        iframe.contentWindow.print();
      }, 100);

      // 打印后回调 + 清理
      iframe.contentWindow.onafterprint = () => {
        if (typeof afterPrint === "function") afterPrint();
        document.body.removeChild(iframe);
      };
    } catch (error) {
      console.error("Print error:", error);
      document.body.removeChild(iframe);
    }
  };

  document.body.appendChild(iframe);
  iframe.src = "about:blank"; // 确保 iframe 加载
}

使用示例

1. 基本用法(直接打印指定ID元素)

printElement("content-to-print");

2. 高级用法(自定义打印标题、样式、回调)

printElement("content-to-print", {
  title: "订单详情",
  includeGlobalStyles: false, // 不继承原页面的全局样式
  beforePrint: () => console.log("即将打印..."),
  afterPrint: () => console.log("打印完成!"),
});

关键优化点

  1. 直接获取原DOM元素

    • 使用 elementToPrint.outerHTML 复制整个元素结构,包括其样式和子元素。

  2. 可选继承全局样式

    • includeGlobalStyles 决定是否复制原页面的 <style> 和 <link rel="stylesheet">,避免打印样式丢失。

  3. 打印前/后回调

    • beforePrint:可在打印前修改 iframe 内容(如隐藏不需要打印的部分)。

    • afterPrint:打印完成后执行清理或后续操作。

  4. 自动清理 iframe

    • 打印完成后自动移除 iframe,避免内存泄漏。

  5. 兼容性优化

    • setTimeout 确保 iframe 完全加载后才打印。

    • focus() 提升部分浏览器的兼容性。

posted @ 2025-07-15 10:49  ヤBestァ玉露い  阅读(62)  评论(0)    收藏  举报