局部打印实现
  
引言: 通常实现打印功能,我们会通过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日