【前端】使用window.print() 前端实现网页打印详细教程(含代码示例)

在这里插入图片描述

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。
🤓 同时欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深度学习从0到1系列文章。
🌼 同时洲洲已经建立了程序员技术交流群,如果您感兴趣,可以私信我加入社群,可以直接vx联系(文末有名片)v:bdizztt
🖥 随时欢迎您跟我沟通,一起交流,一起成长、进步!点此也可获得联系方式~

本文目录

  • 前言
  • 一、打印基础知识
  • 二、打印控制
    • 2.1 使用打印样式表
    • 2.2 使用媒介查询
    • 2.3 内联样式使用media属性
    • 2.4 css中使用@import引入打印样式表
    • 2.5 打印指定区域
    • 2.6 插入分页
    • 2.7 设置打印布局
    • 2.8 去除页眉页脚
  • 三、示例代码打印方法
  • 总结

前言

在前端开发中,有时我们需要提供打印网页内容的功能,让最终用户能够将网页上的特定部分打印成纸质文档。

虽然浏览器提供了自己的打印预览和打印功能,但使用 JavaScript 的 window.print() 方法可以更灵活地控制打印内容和样式。

本文洲洲将详细介绍如何使用 window.print() 方法实现网页打印,并提供代码示例。

一、打印基础知识

在开始之前,我们需要了解基本的打印流程:

1、用户触发打印操作,这可以是一个按钮点击事件。
2、JavaScript 捕获事件并调用 window.print() 方法。
3、浏览器显示打印预览窗口,用户可以设置打印选项并打印。

print() 方法用于打印当前窗口的内容。

调用 print() 方法会产生一个打印预览弹框,让用户可以设置打印请求。

最简单的打印就是直接调用window.print(),当然用 document.execCommand(‘print’) 也可以达到同样的效果。

默认打印页面中body里的所有内容。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>打印-洲洲</title>
</head>
<body>
  <input type="button" value="打印此页面" onclick="printpage()" />
  <div>内容</div>
  <script>
    function printpage() {
      window.print()
    }
  </script>
</body>
</html>

比方说我们用上面的代码,进行一个简单的尝试:
在这里插入图片描述
但是这样会存在一定的问题,那就是直接调用print()方法去打印网页内容,事先调整好的布局和样式都没法实现,所以有哪些方法可以帮助我们改善打印的用户体验呢?

二、打印控制

2.1 使用打印样式表

配置一份打印样式表print.css,引入到HTML文档,在 上加上一个 media=“print” 来标识这是打印机才会应用的样式表,这样打印就会默认将该样式表应用到文档中。

<link href="/path/print.css" media="print" rel="stylesheet" />

2.2 使用媒介查询

要修改的样式没有很多的时候,其实完全不需要重新写个样式表,写上一个媒介查询也可以达到同样的效果,如:

@media print {
  h1 {
    font-size: 20px;
    color: red;
  }
}

2.3 内联样式使用media属性

<style type="text/css" media="print">
   // 打印样式
</style>

2.4 css中使用@import引入打印样式表

@import url("/path/print.css") print;

2.5 打印指定区域

在需要打印的正文内容所对应的html开始处加上标识,结尾处加上标识,截取打印标识之间的内容替换body的内容,调用打印print()方法。

<body>
  <input type="button" value="打印此页面" onclick="printpage()" />
 
  <!--startprint-->
  <div id="printContent">打印内容</div>
  <!--endprint-->
 
  <script>
    function printpage() {
      let oldStr = window.document.body.innerHTML; // 获取body的内容
      let start = "<!--startprint-->"; // 开始打印标识, 17个字符
      let end = "<!--endprint-->"; // 结束打印标识
      let newStr = oldStr.substr(oldStr.indexOf(start) + 17); // 截取开始打印标识之后的内容
      newStr = newStr.substring(0, newStr.indexOf(end)); // 截取开始打印标识和结束打印标识之间的内容
      window.document.body.innerHTML = newStr; // 把需要打印的指定内容赋给body
      window.print(); // 调用浏览器的打印功能打印指定区域
      window.document.body.innerHTML = oldStr; // body替换为原来的内容
    }
  </script>
</body>

或者也可以将需要打印的内容用一个大的div包裹,打印时将body的内容替换为该div的内容,调用打印print()方法。

<body>
  
  <input type="button" value="打印此页面" onclick="printpage()" />
  <div id="printContent">打印内容</div>
 
  <script>
    function printpage() {
      let newstr = document.getElementById("printContent").innerHTML;
      let oldstr = document.body.innerHTML;
      document.body.innerHTML = newstr;
      window.print();
      document.body.innerHTML = oldstr;
      return false;
    }
  </script>
</body>

也可以在打印之前,我们可以使用 JavaScript 来隐藏那些不需要打印的元素。

function printContent() {
    // 隐藏不需要打印的元素
    document.body.style.display = 'none';
    
    // 调用打印
    window.print();
    
    // 打印完成后恢复显示
    window.onfocus = function() {
        document.body.style.display = '';
        window.onfocus = null; // 清除事件监听
    };
}

2.6 插入分页

/* 在h1元素前始终插入分页符 */
@media print {
    h1 {page-break-before: always;}
}
/* 在 .footer 元素后始终插入分页符 */
@media print {
    .footer {page-break-after: always;}
}
/* 避免在 <pre> 与 <blockquote> 元素中插入分页符 */
@media print {
    pre, blockquote {page-break-inside: avoid;}
}

2.7 设置打印布局

 @media print {
    @page {
      /* 纵向 */
      size: portrait; 
 
      /* 横向 */
      size: landscape;
 
      /* 边距 上右下左 */
      margin: 1cm 2cm 1cm 2cm;
    }
  }

2.8 去除页眉页脚

当页眉打印默认有页眉页脚信息,展现到页面外边距范围,我们可以通过去除页面模型page的外边距,使得内容不会延伸到页面的边缘,再通过设置 body 元素的 margin 来保证 A4 纸打印出来的页面带有外边距。

@media print {
  @page {
    margin: 0;
  }
  body {
    margin: 1cm;
  }
}

三、示例代码打印方法

在utils下新建print.js文件:

export default function printHtml(html) {
  let style = getStyle();
  let container = getContainer(html);
 
  document.body.appendChild(style);
  document.body.appendChild(container);
 
  getLoadPromise(container).then(() => {
    window.print();
    document.body.removeChild(style);
    document.body.removeChild(container);
  });
}
 
// 设置打印样式
function getStyle() {
let styleContent = `#print-container {
    display: none;
}
@media print {
    body > :not(.print-container) {
        display: none;
    }
    html,
    body {
        display: block !important;
    }
    #print-container {
        display: block;
    }
}`;
  let style = document.createElement("style");
  style.innerHTML = styleContent;
  return style;
}
 
// 清空打印内容
function cleanPrint() {
  let div = document.getElementById('print-container')
  if (!!div) {
    document.querySelector('body').removeChild(div)
  }
}
 
// 新建DOM,将需要打印的内容填充到DOM
function getContainer(html) {
  cleanPrint()
  let container = document.createElement("div");
  container.setAttribute("id", "print-container");
  container.innerHTML = html;
  return container;
}
 
// 图片完全加载后再调用打印方法
function getLoadPromise(dom) {
  let imgs = dom.querySelectorAll("img");
  imgs = [].slice.call(imgs);
 
  if (imgs.length === 0) {
    return Promise.resolve();
  }
 
  let finishedCount = 0;
  return new Promise(resolve => {
    function check() {
      finishedCount++;
      if (finishedCount === imgs.length) {
        resolve();
      }
    }
    imgs.forEach(img => {
      img.addEventListener("load", check);
      img.addEventListener("error", check);
    })
  });
}

引入print文件,传入需要打印的DOM元素即可:

import printHtml from "@/utils/print.js"
 
export default {
  methods: {
    print() {
      let printData = `<div>打印内容</div>`
      printHtml(printData)
    }
  },
}

总结

📝Hello,各位看官老爷们好,我已经建立了CSDN技术交流群,如果你很感兴趣,可以私信我加入我的社群。

📝社群中不定时会有很多活动,例如每周都会包邮免费送一些技术书籍及精美礼品、学习资料分享、大厂面经分享、技术讨论谈等等。

📝社群方向很多,相关领域有Web全栈(前后端)、人工智能、机器学习、自媒体副业交流、前沿科技文章分享、论文精读等等。

📝不管你是多新手的小白,都欢迎你加入社群中讨论、聊天、分享,加速助力你成为下一个大佬!

📝想都是问题,做都是答案!行动起来吧!欢迎评论区or后台与我沟通交流,也欢迎您点击下方的链接直接加入到我的交流社群!~ 跳转链接社区~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/696212.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vuex3学习笔记

文章目录 1&#xff0c;入门案例辅助函数 2&#xff0c;mutations传参辅助函数 3&#xff0c;actions辅助函数 4&#xff0c;getters辅助函数 5&#xff0c;模块拆分6&#xff0c;访问子模块的state辅助函数 7&#xff0c;访问子模块的getters辅助函数 8&#xff0c;访问子模块…

Java--递归

1.递归就是A方法调用A方法&#xff0c;也就是调用自己本身 2.利用递归可以用简单的程序来解决一些复杂的问题&#xff0c;它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解&#xff0c;递归策略只需少量的程序就可描述出解题过程所需要的多次重复…

【MySQL数据库】:MySQL索引特性

目录 索引的概念 磁盘 磁盘的基本特征 MySQL与磁盘交互的基本单位 索引的理解 建立测试表 理解单个Page 理解多个Page 页目录 单页情况 多页情况 索引的数据结构 聚簇索引 VS 非聚簇索引 索引操作 创建主键索引 创建唯一索引 创建普通索引 创建全文索引 查询…

Nginx服务配置

一、Nginx服务的主配置文件nginx.conf vim /usr/local/nginx/conf/nginx.conf 全局块&#xff1a;全局配置&#xff0c;对全局生效&#xff1b;events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接&#xff1b;http块&#xff1a;配置代理&#xff0c;缓存&#xff0c…

重温共射放大电路

1、放大概念 小功率信号变成一个大功率信号&#xff0c;需要一个核心器件做这件事&#xff0c;核心器件的能量由电源提供&#xff0c;通过核心器件用小功率的信号去控制大电源&#xff0c;来实现能量的转换和控制&#xff0c;前提是不能失真&#xff0c;可以用一系列正弦波进行…

conda 创建环境失败

conda create -n pylableimg python3.10在conda &#xff08;base&#xff09;环境下&#xff0c;创建新的环境&#xff0c;失败。 报错&#xff1a; LookupError: didn’t find info-scipy-1.11.3-py310h309d312_0 component in C:\Users\Jane.conda\pkgs\scipy-1.11.3-py310h…

RK3568-修改fiq-debugger调试串口

瑞芯微SDK默认将uart2_m0作为调试串口,以下方法将调试串口修改为uart5_m1。修改bootloader 修改/OK3568-linux-source/rkbin/tools/ddrbin_param.txt文件,5表示串口5。1表示复用m1。执行./ddrbin_tool ddrbin_param.txt ../bin/rk35/rk3568_ddr_1560MHz_v1.11.bin命令修改ub…

素数的无穷大的证明

素数的无穷大——欧几里得的证明 文章目录 一、说明二、欧几里得证据三、哥德巴赫对素数无穷性的证明&#xff08;1730&#xff09;四、Frstenberg 对素数无穷性的证明(1955)五、库默尔对欧几里得证明的重述 一、说明 众所周知&#xff0c;素数是无限多的。然而&#xff0c;两…

代码随想录算法训练营第36期DAY56

DAY56 套磁很顺利&#xff0c;发现又有书读了&#xff01; 300最长递增子序列 朴素法&#xff0c;这个好想&#xff0c;但是不对&#xff0c;比如 0 1 0 3 2 3 我的算法会找出0 1 3作为答案&#xff0c;而不是0 1 2 3 可以看出&#xff0c;后面的状态依赖于前面的状态&am…

CMake详细解读

原文来自&#xff1a;CMake 保姆级教程 视频来自B站&#xff1a;CMake 保姆级教程C/C 1、快速操作&#xff1a; 原文来自&#xff1a;在 VScode 中使用 CMake 快速创建cpp工程 首先创建一个 C/C 工程文件夹 CALC&#xff0c;用 VSCode 打开&#xff0c;目录结构如下&#x…

探索软件工程师在新能源汽车研发中的角色与贡献

随着全球对可持续发展的关注不断增加&#xff0c;新能源汽车的研发与应用成为了汽车行业的一个重要方向。作为软件工程师&#xff0c;参与新能源汽车研发不仅能够推动科技创新&#xff0c;还能为环保事业贡献力量。本文将深入探讨软件工程师在新能源汽车研发中的具体贡献、所需…

如何画系统架构图学习

原文链接:https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/%E4%BB%8E%200%20%E5%BC%80%E5%A7%8B%E5%AD%A6%E6%9E%B6%E6%9E%84/51%20%E5%A6%82%E4%BD%95%E7%94%BB%E5%87%BA%E4%BC%98%E7%A7%80%E7%9A%84%E8%BD%AF%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E5%9B%BE%EF…

C语言学习系列:初识C语言

前言&#xff0c;C语言是什么 语言&#xff0c;比如中文、英语、法语、德语等&#xff0c;是人与人交流的工具。 C语言也是语言&#xff0c;不过是一种特殊的语言&#xff0c;是人与计算机交流的工具。 为什么叫C语言呢&#xff1f; 这就要从C语言的历史说起了。 一&#…

RAG vs Fine-Tuning 微调哪种大模型(LLM)技术更好?

数据科学和机器学习的研究人员和从业者都在不断探索创新策略来增强语言模型的能力。在众多方法中&#xff0c;出现了两种突出的技术&#xff0c;即检索增强生成 (RAG)和微调。本文旨在探讨模型性能的重要性以及 RAG 和微调策略的比较分析。 模型性能在 NLP 中的重要性 增强用…

[数据集][图像分类]黑色素瘤分类数据集10015张7类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;10015 分类类别数&#xff1a;7 类别名称:[“0”,“1”,“2”,“3”,“4”,…

Java学习 - MyBatis - 入门实例详解

前言 在上一篇文章中&#xff0c;我们讨论了持久化的概念&#xff0c;并简要介绍了 MyBatis。今天我们将深入到 MyBatis 的实际应用中&#xff0c;通过创建一个入门实例来展示如何使用 MyBatis 执行基本的 CRUD&#xff08;创建、读取、更新、删除&#xff09;操作。这个过程将…

demo xshell (程序替换 工作目录 内建命令)

1.程序替换 在学习完一些列的进程替换接口之后我们大概就能知道&#xff0c;我们的环境变量以及命令行参数是如何传递给子进程的&#xff0c;这些参数是我们在调用进程替换时就传给了子进程的数据。 那么如果我们自己要实现一个简单的命令行解释器&#xff0c;我们是不是首先…

记录某书请求返回406及响应{“code“:-1,“success“:false}

今天测试某个平台的爬虫时使用requests post请求正常写了个测试脚本把各种参数带上出来以后出现了406情况&#xff0c;和网站数据是完全一样的 以为是 X-S、X-T参接不对&#xff0c;但在postman里测试又是可以的成功&#xff0c;以为是检验了参数顺序&#xff0c;测试发现也没…

Ubuntu 24.04 LTS 安装配置 MySQL Community Server 8.4.0 LTS

1 安装 Apt Repository ​​​​​​​地址MySQL :: Download MySQL APT Repository sudo dpkg -i mysql-apt-config_0.8.30-1_all.deb #安装mysql 8.4 lts sudo apt update sudo apt-get install mysql-server #修改mysql root密码策略 2 查看版本 testtest:~$ mysqld --v…

mysql 数据库datetime 类型,转换为DO里面的long类型后,只剩下年了,没有了月和日

解决方法也简单&#xff1a; 自定义个一个 Date2LongTypeHandler <resultMap id"BeanResult" type"XXXX.XXXXDO"><result column"gmt_create" property"gmtCreate" jdbcType"DATE" javaType"java.lang.Long&…