局部打印实现
引言: 通常实现打印功能,我们会通过window.print()
来实现,但是这个方法没办法做到局部打印,例如我想打印一个dom的内容。其实只需要做一些简单处理便可以实现打印了。
方案一(🤔)
将页面DOM临时替换成局部DOM
1 2 3 4 5 6 7 8 9 10 11 12 13
| <body> <div class="container"> <h1>Hello Word</h1> <button onclick="printPage()">打印页面</button> <div class="print-area"> <div class="content"> <h2>Title</h2> <p>把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。 </p> </div> </div> </div> </body>
|
例如上方的结构,我想打印.print-area
的内容,我可以这么操作:
1 2 3 4 5 6 7 8 9 10 11
| const printPage = () =>{ const printAreaDom = document.querySelector('.print-area') const originContent = document.body.innerHTML
document.body.innerHTML = printAreaDom.innerHTML window.print() document.body.innerHTML = originContent }
|
这样做虽然能够打印出想要的内容,但是在复杂的环境下,可能会导致dom中的监听事件丢失。
方案二(🤩)
使用CSS媒体查询@print
直接贴代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <head> <style> @media print { :has(.print-area)> :not(.print-area):not(:has(.print-area)) { display: none; } .print-area { padding: 32px; } } </style> </head> <body> <div class="container"> <h1>Hello Word</h1> <button onclick="printPage()">打印页面</button> <div class="print-area"> <div class="content"> <h2>Title</h2> <p>把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。把自己当傻瓜,不懂就问,你会学的更多。 </p> </div> </div> </div>
<script> function printPage() { window.print(); } </script> </body>
|
经过如上的媒体查询设置,window.print()
就只会打印.print-area
中的内容了,其他的内容就会被隐藏。它的作用是选择拥有类名为 .print-area
的祖先元素但不是 .print-area
类型的子孙元素。换句话说,它选择了所有不包含 .print-area
类的元素,并且这些元素的祖先元素中有包含 .print-area
类的元素。对于这些元素,将它们的 display
属性设置为 none
,在打印时隐藏它们。*不过要注意的是,该方法只适用于支持:has
选择器的运行环境下,好在目前的主流浏览器都支持这个特性,应用MDN里的一句话:
Since December 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
译: 自2023年12月起,此功能适用于最新设备和浏览器版本。此功能可能无法在较旧的设备或浏览器中工作。
兼容性明细

「在没有IE的新时代里,放心使用」
若是对兼容性有苛刻的要求的话,可以使用成熟的三方库实现打印。在Electron、Tauri、uniapp这种跨平台框架中,应该去尝试使用像:has
选择器这样的新花样来帮助我们的屎山代码化繁为简。
🔗;
MDN对:has()选择器的介绍
👋;
前端, 技术分享 — 2024年3月30日