解决思路
window
对象可以触发,且打印的是body
下所有元素,默认是不能指定需要打印元素的,
而window
对象在js中有三个地方可以获取
- 当前页面的
window
对象iframe
元素内的window
对象- 用
window.open
方法生成的window
对象
优缺点
1. 当前页面的window
对象
如果想实现利用当前页面的
window
对象打印指定元素,则需要在打印时替换body
元素
优点:
- 省事,直接替换
body
下元素即可缺点:
- 如果是在纯手写
html页面文件
,这是没问题的,但如果是通过vue
、react
等node.js
第三方框架生成的页面,则是不行的,因为第三方框架,会将部分的js
和css
放在body
下,所以如果直接替换,则会使部分Element
和CSS
失效
let oldStr=window.document.body.innerHTML;
let newStr=document.querySelector('xxxxx').innerHTML;
window.document.body.innerHTML=newStr;
window.print();
window.document.body.innerHTML=oldStr;
2. iframe
元素内的window
对象(推荐)
iframe
元素打印元素是最可靠的,但iframe
存在很多的浏览器安全限制,所以需要保证生成的iframe
必须和当前页面是同源的,不然是无法操作内部元素的
优点:
- 无感知打印,在页面上不会产生任何的变化;
- 可以做更多的自定义操作
缺点:
- 需要在使用前后删除生成的元素
function removeIframe(){
const iframeEL=document.querySelector('.target-el-iframe');
if(iframeEl){
iframeEl.remove();
}
}
function print(){
removeIframe();
//目标元素
const info=document.querySelector('.target-el');
//创建iframe
const iframeEl= document.createElement('iframe');
iframeEl.class='target-el-iframe';
//将元素放置最底层,防止其覆盖了其他元素
iframeEl.style.position="fixed"
iframeEl.style.zIndex=-99;
//添加到页面
document.querySelector('body').append(iframeEl)
const documentEl=iframeEl.contentDocument;
//深度拷贝目标元素,如果不拷贝,则会将目标元素移动到iframe中
documentEl.body.append(info.cloneNode(true))
//去除打印的页眉和页脚
const style=document.createElement('style')
style.media="print";
style.innerText=`
@page {
size: auto;
margin: 0mm;
}`
//添加答应内容
documentEl.head.append(style);
//打印
iframeEl.contentWindow.print()
}
3. window.open
生成的window
对象(不推荐)
使用
window.open
生成的window
对象,是最不推荐的一个,因为打印时的打印窗体会跟随window
窗体,所以需要打开的window
窗体不是源窗体大小,则会出现ui视觉
感受;
优点:
- 因为他和iframe一样都是生成的新
window
对象,所以都可以进行自定义操作,且不会影响源window
缺点:
open
时会生成真实的子窗体,所以无法做到无感知调用打印
let openWindow=window.open('','','','');
openWindow.document.write(document.querySelector('xxx').innerHTML);
openWindow.print();
openWindow.close();