0

0

利用JavaScript和Data URI实现网页特定元素打印教程

DDD

DDD

发布时间:2025-10-16 12:21:12

|

560人浏览过

|

来源于php中文网

原创

利用JavaScript和Data URI实现网页特定元素打印教程

本教程详细介绍了如何使用javascript将网页中的特定html元素(如收据)打印到pdf或纸张。通过将目标元素的html内容封装为data uri并在新窗口中打开,结合内联javascript触发自动打印,实现了一种高效且用户友好的局部内容打印解决方案,避免了复杂的内容隐藏与恢复操作。

在构建复杂的网页应用时,经常会遇到需要打印页面特定区域内容的需求,例如电商网站的订单收据、报告或证书。传统的做法可能涉及通过JavaScript动态隐藏或显示页面元素,但这通常会导致页面闪烁或复杂的DOM操作。本教程将介绍一种更为优雅且自动化的方法,利用Data URI和内联JavaScript实现特定元素的打印功能。

核心原理概述

本方案的核心在于以下几个关键技术点:

  1. Data URI (数据统一资源标识符):Data URI 允许我们将小型文件直接嵌入到HTML、CSS或JavaScript中,而无需外部链接。在这里,我们将待打印的HTML内容编码成一个Data URI,浏览器可以将其作为一个独立的HTML页面进行渲染。
  2. window.print() 方法:这是浏览器内置的打印功能,调用它会弹出操作系统的打印对话框,允许用户选择打印机或保存为PDF。
  3. 内联 JavaScript:为了实现自动打印,我们将在Data URI所承载的HTML内容中嵌入一段JavaScript代码,使其在新页面加载完成后自动调用 window.print()。
  4. 动态样式注入:为了确保打印内容的最佳呈现,我们可以在打印前动态注入额外的CSS样式,例如居中布局。

HTML 结构准备

首先,需要将你希望打印的特定内容(例如收据表格)封装在一个独立的容器元素中。这样做有助于JavaScript精确地获取其HTML内容。同时,为了打印时的样式一致性,建议将与该内容相关的CSS样式直接嵌入到该容器内部或其子元素中,以确保在新打开的打印页面中样式能够正确应用。

以下是一个收据表格的HTML结构示例,它被包裹在一个 section 标签内,并且其样式直接嵌入在表格中:

立即学习Java免费学习笔记(深入)”;

<section class="receipt-section">
    <table class="receipt">
      <style>
        /* 收据表格的专用样式 */
        .receipt {
          border-collapse: collapse;
          max-width: 80%;
          font-family: sans-serif;
          /* 初始样式,打印时可能需要调整 */
        }

        .receipt td {
          padding: .5em;
        }

        .receipt tr:nth-child(even) {
          border: 1px solid #333;
          border-inline: none;
          background: #ddd;
        }

        .receipt tr:nth-child(odd) {
          background: #fff
        }

        .header-Uprice,
        .item-Uprice,
        .header-qty,
        .item-qty {
          text-align: center
        }

        .total {
          border-bottom: 3px double #000
        }
      </style>
      <tr class="table-headers">
        <td class="header-id">#</td>
        <td class="header-desc">Item Description</td>
        <td class="header-Uprice">Unit Price</td>
        <td class="header-qty">Qty</td>
        <td class="header-price">Price</td>
      </tr>
      <tr class="item" id="1">
        <td class="item-id">1</td>
        <td class="item-desc">Dummy Item1</td>
        <td class="item-Uprice">200$</td>
        <td class="item-qty">1</td>
        <td class="item-price">200$</td>
      </tr>
      <tr class="item" id="2">
        <td class="item-id">2</td>
        <td class="item-desc">Dummy Item2</td>
        <td class="item-Uprice">75$</td>
        <td class="item-qty">1</td>
        <td class="item-price">75$</td>
      </tr>
      <tr class="item" id="3">
        <td class="item-id">3</td>
        <td class="item-desc">Dummy Item3</td>
        <td class="item-Uprice">100$</td>
        <td class="item-qty">2</td>
        <td class="item-price">200$</td>
      </tr>
      <tr class="total">
        <td>Total</td>
        <td></td>
        <td></td>
        <td></td>
        <td>475$</td>
      </tr>
    </table>
</section>

JavaScript 实现步骤

接下来是实现打印功能的JavaScript代码。我们将创建一个函数,该函数在被调用时执行以下操作:

  1. 获取目标内容并注入打印逻辑 首先,获取包含收据的 table 元素。然后,向其内部动态注入一个 <script> 标签。这个脚本会在新页面加载完成后执行,首先应用一些额外的打印样式(例如居中),然后调用 window.print() 触发打印。

    function printReceipt() {
      const receiptTable = document.querySelector('.receipt');
      // 动态注入用于打印居中的CSS样式,这里通过修改已有的style标签实现
      // 注意:这里假设receiptTable内部有一个<style>标签,或者可以直接在receiptTable上添加style属性
      const cssCenteringScript = `
        const styleTag = document.querySelector('table.receipt > style');
        if (styleTag) {
          styleTag.innerHTML += '.receipt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; }';
        } else {
          // 如果没有内联style标签,则创建一个并注入
          const newStyle = document.createElement('style');
          newStyle.innerHTML = '.receipt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; }';
          document.head.appendChild(newStyle);
        }
      `;
    
      // 注入自动打印的脚本到收据表格内容中
      // 注意:这里将脚本直接添加到receiptTable的innerHTML,确保它在新页面中被执行
      receiptTable.innerHTML += `<script>window.onload = () => { ${cssCenteringScript}; window.print(); }</script>`;
    
      // ... 后续步骤
    }
  2. 构建 Data URI 在注入脚本后,获取包含整个 section 的完整HTML内容。然后,使用 encodeURIComponent 对这段HTML字符串进行编码,并前缀 data:text/html, 来构建Data URI。

    function printReceipt() {
      // ... (前面注入脚本的代码) ...
    
      const receiptSectionHTML = document.querySelector('.receipt-section').innerHTML;
      const dataUri = 'data:text/html,' + encodeURIComponent(receiptSectionHTML);
    
      // ... 后续步骤
    }
  3. 在新窗口中打开并触发打印 最后,使用 window.open() 方法在新标签页或新窗口中打开这个Data URI。由于Data URI中包含了自动打印的脚本,新页面加载后将立即弹出打印对话框。

    function printReceipt() {
      const receiptTable = document.querySelector('.receipt');
      const cssCenteringScript = `
        const styleTag = document.querySelector('table.receipt > style');
        if (styleTag) {
          styleTag.innerHTML += '.receipt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; }';
        } else {
          const newStyle = document.createElement('style');
          newStyle.innerHTML = '.receipt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; }';
          document.head.appendChild(newStyle);
        }
      `;
    
      // 保存原始HTML,以便在注入后可以恢复
      const originalReceiptTableHTML = receiptTable.innerHTML;
    
      receiptTable.innerHTML += `<script>window.onload = () => { ${cssCenteringScript}; window.print(); }</script>`;
    
      const receiptSectionHTML = document.querySelector('.receipt-section').innerHTML;
      const dataUri = 'data:text/html,' + encodeURIComponent(receiptSectionHTML);
    
      window.open(dataUri, '_blank'); // 在新标签页中打开并触发打印
    
      // 打印完成后(或者立即),恢复原始HTML,移除注入的脚本
      // 注意:由于是新窗口打开,这里立即恢复对当前页面DOM没有影响
      receiptTable.innerHTML = originalReceiptTableHTML; 
    }

完整代码示例

将上述步骤整合,并添加一个按钮来触发 printReceipt 函数:

Napkin AI
Napkin AI

Napkin AI 可以将您的文本转换为图表、流程图、信息图、思维导图视觉效果,以便快速有效地分享您的想法。

下载
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>打印特定元素教程</title>
    <style>
        body {
            font-family: sans-serif;
            margin: 20px;
        }
        .printButton {
            padding: 10px 20px;
            font-size: 16px;
            cursor: pointer;
            margin-bottom: 20px;
        }
        /* 页面其他内容,确保它不会被打印 */
        .other-content {
            background-color: #f0f0f0;
            padding: 20px;
            border: 1px solid #ccc;
            margin-top: 20px;
        }
    </style>
</head>
<body>

    <h1>网页特定元素打印示例</h1>
    <button class="printButton">打印收据</button>

    <div class="other-content">
        这是页面上的其他内容,不应被打印。
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    </div>

    <section class="receipt-section">
        <table class="receipt">
          <style>
            /* 收据表格的专用样式 */
            .receipt {
              border-collapse: collapse;
              max-width: 80%; /* 原始页面显示时的最大宽度 */
              font-family: sans-serif;
              width: 100%; /* 打印时通常希望宽度占满 */
            }

            .receipt td {
              padding: .5em;
            }

            .receipt tr:nth-child(even) {
              border: 1px solid #333;
              border-inline: none;
              background: #ddd;
            }

            .receipt tr:nth-child(odd) {
              background: #fff
            }

            .header-Uprice,
            .item-Uprice,
            .header-qty,
            .item-qty {
              text-align: center
            }

            .total {
              border-bottom: 3px double #000
            }
          </style>
          <tr class="table-headers">
            <td class="header-id">#</td>
            <td class="header-desc">Item Description</td>
            <td class="header-Uprice">Unit Price</td>
            <td class="header-qty">Qty</td>
            <td class="header-price">Price</td>
          </tr>
          <tr class="item" id="1">
            <td class="item-id">1</td>
            <td class="item-desc">Dummy Item1</td>
            <td class="item-Uprice">200$</td>
            <td class="item-qty">1</td>
            <td class="item-price">200$</td>
          </tr>
          <tr class="item" id="2">
            <td class="item-id">2</td>
            <td class="item-desc">Dummy Item2</td>
            <td class="item-Uprice">75$</td>
            <td class="item-qty">1</td>
            <td class="item-price">75$</td>
          </tr>
          <tr class="item" id="3">
            <td class="item-id">3</td>
            <td class="item-desc">Dummy Item3</td>
            <td class="item-Uprice">100$</td>
            <td class="item-qty">2</td>
            <td class="item-price">200$</td>
          </tr>
          <tr class="total">
            <td>Total</td>
            <td></td>
            <td></td>
            <td></td>
            <td>475$</td>
          </tr>
        </table>
    </section>

    <script>
        function printReceipt() {
            const receiptTable = document.querySelector('.receipt');

            // 确保在获取innerHTML之前,将可能需要居中的样式注入到新页面的head中
            // 这里的cssCenteringScript会作为字符串被注入到新页面的<script>中执行
            const cssCenteringScript = `
                const styleTag = document.createElement('style');
                styleTag.innerHTML = '.receipt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; max-width: 80%; width: auto; }';
                document.head.appendChild(styleTag);
            `;

            // 保存原始HTML,以便在注入后可以恢复
            const originalReceiptTableHTML = receiptTable.innerHTML;

            // 注入自动打印的脚本到收据表格内容中
            // 这个脚本会在新打开的Data URI页面中执行
            receiptTable.innerHTML += `<script>window.onload = () => { ${cssCenteringScript}; window.print(); };<\/script>`;

            const receiptSectionHTML = document.querySelector('.receipt-section').innerHTML;
            const dataUri = 'data:text/html,' + encodeURIComponent(receiptSectionHTML);

            window.open(dataUri, '_blank'); // 在新标签页中打开并触发打印

            // 恢复原始HTML,移除注入的脚本,避免影响当前页面的DOM
            // 这一步在window.open之后立即执行,不会影响新打开的Data URI页面
            receiptTable.innerHTML = originalReceiptTableHTML; 
        }

        const button = document.querySelector('.printButton');
        button.addEventListener('click', printReceipt);
    </script>

</body>
</html>

注意事项与优化

  1. 浏览器兼容性:window.open() 和 data: URI 在现代浏览器中普遍支持,但某些浏览器可能会有对Data URI长度的限制。对于非常大的HTML内容,这种方法可能不适用。

  2. 安全性:使用 window.open() 打开 data: URI 通常被认为是安全的,因为内容是本地生成的。然而,如果Data URI的内容来自不可信的第三方,则可能存在跨站脚本(XSS)风险。在本例中,内容来自当前页面DOM,因此风险较低。

  3. 打印样式控制 (@media print):对于更专业的打印布局,推荐使用CSS的 @media print 媒体查询。通过定义专门的打印样式表,可以精确控制打印时的页面布局、字体大小、隐藏非打印元素等,而无需JavaScript的动态注入。例如:

    /* style.css */
    /* 默认屏幕样式 */
    .receipt-section { display: block; }
    .print-button { display: block; }
    
    @media print {
        /* 打印时隐藏所有非收据内容 */
        body > *:not(.receipt-section) {
            display: none;
        }
        /* 让收据居中 */
        .receipt-section {
            width: 100%;
            margin: auto;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        /* 确保收据表格宽度占满 */
        .receipt {
            width: 100%;
            max-width: none; /* 移除屏幕样式中的最大宽度限制 */
        }
    }

    然后,JavaScript只需调用 window.print() 即可,无需构建Data URI和注入脚本。这种方法通常更健壮和易于维护。本教程介绍的方法是应对特定场景(如需要完全隔离打印内容)的一种灵活变通方案。

  4. 用户体验:window.open() 可能会被浏览器的弹窗拦截器阻止,尤其是在用户没有明确交互(如点击按钮)的情况下。确保用户行为触发此函数可以避免此问题。

总结

通过将特定HTML内容封装为Data URI,并巧妙地利用内联JavaScript在新页面加载时触发 window.print(),我们可以实现一种高效且用户友好的局部内容打印解决方案。虽然这种方法在某些方面可能略显“非传统”,但它提供了一种无需复杂DOM操作即可实现局部打印的有效途径。在实际项目中,开发者应根据具体需求权衡其与更标准的 @media print 方案的优劣,选择最适合的实现方式。

相关文章

全能打印神器
全能打印神器

全能打印神器是一款非常好用的打印软件,可以在电脑、手机、平板电脑等设备上使用。支持无线打印和云打印,操作非常简单,使用起来也非常方便,有需要的小伙伴快来保存下载体验吧!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

193

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

19

2026.02.03

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

211

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

325

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

293

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

179

2025.08.07

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 43.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号