核心:
- 直接调用window.print()
- iframe 方式:iframe.contentWindow.print();
方式一:借助创建iframe元素,实现指定区域打印
handlePrint(){
const iframeEL=document.querySelector('.target-el-iframe');
if(iframeEL){
iframeEL.remove();
}
//目标元素
const info=document.querySelector('.print');
//创建iframe
const iframeEl= document.createElement('iframe');
iframeEl.classList.add('target-el-iframe')
iframeEl.setAttribute('style','width:90%')
//添加到页面
document.body.appendChild(iframeEl)
const doc = iframeEl.contentWindow.document
doc.write('<div class="print-iframe">' + info.innerHTML + '</div>')
doc.write('<style>@page{size:auto;margin: 0.5cm 1cm 0cm 1cm;}</style>')
doc.close()
//引入第三方样式文件
const link = doc.createElement('link');
link.rel = 'stylesheet';
link.href = '/static/print/print.less';
doc.head.appendChild(link);
//打印
iframeEl.onload = () => {
iframeEl.contentWindow.print()
}
},
思路:
1 判断是否有上次创建的iframe元素,若有,移除
2创建iframe元素,并给class类名,方便移除
3 设置打印页面内容
4 设置页面内容样式(因为有些样式会丢失,这里可以补上)
5 调用浏览器的打印方法实现打印
注意:
1 可能会出现样式丢失,可添加第三方样式文件
const doc = iframeEl.contentWindow.document;
const link = doc.createElement('link');
link.rel = 'stylesheet';
link.href = '/static/print/print.css';
doc.head.appendChild(link);
示例:将样式文件放在public文件下的/static/print/print.css
@import url('./antd.css'); //引入antd样式文件
方式二:使用媒体查询
直接使用window.print()
@media print {
body * {
visibility: hidden;
}
//打印区
#print-area, #print-area * {
visibility: visible;
}
#print-area {
position: absolute;
left: 0;
top: 0;
}
}
思路:
1先将全部元素不可见
2 将打印区设置为可看见
方法三:使用html2canvas结合iframe
好处:相较于方法一,不会出现样式丢失
缺陷:速度慢
引入html2canvas库
import html2canvas from 'html2canvas'
handlePrint(){
const iframeEL=document.querySelector('.print-iframe');
if(iframeEL){
iframeEL.remove();
}
// 获取要转换为图片的 DOM 元素
const element = document.querySelector('.print');
// 将 DOM 元素转换为 Canvas 对象
html2canvas(element).then(canvas => {
// 创建一个新的图片元素,并将 Canvas 对象作为背景图
const img = new Image();
img.src = canvas.toDataURL('image/png');
img.style.width='100%'
// 在 iframe 文档中添加图片元素
const iframe = document.createElement('iframe');
iframe.style.width='100%'
iframe.classList.add('print-iframe')
document.body.appendChild(iframe)
const doc = iframe.contentWindow.document
doc.body.appendChild(img);
//避免图片没有加载完成就打印
setTimeout(()=>{
iframe.contentWindow.print();
},100)
})
},
方法四 使用PrintJs插件
使用printjs时,遇到的坑:字体不生效,源码中字体统一是12pt,感觉很不理解
printView() {
Printjs({
printable: 'dayin', // 要打印内容的id
type: 'html', // 可以打印html,img详细的可以在官方文档https://printjs.crabbly.com/中查询
targetStyles: ['*'],
// style: workOrderStyle(), // 打印的内容是没有css样式的,此处需要string类型的css样式
// style: `@page{size:auto;margin: 0cm;}`, // 打印的内容是没有css样式的,此处需要string类型的css样式
scanStyles: true,
onLoadingEnd() {
// showPrintNode.value = false
}
})
方法五
插件:vue-print-nb
安装:npm install vue-print-nb --save
引入
// 1. 全局挂载,在main.js添加
import Print from 'vue-print-nb'
Vue.use(Print)
// or
// 2. 自定义指令,在单业务页面添加
import print from 'vue-print-nb'
directives: {
print
}
使用界面:
1 给打印的区域设置id值
<a-button type="primary" v-print="print">打印</a-button>
export default {
name: 'index',
data(){
let that = this
return {
print: {
id: 'printContent',
popTitle: '配置页眉标题', // 打印配置页上方的标题
extraHead: '打印', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
preview: true, // 是否启动预览模式,默认是false
previewTitle: '预览的标题', // 打印预览的标题
previewPrintBtnLabel: '预览结束,开始打印', // 打印预览的标题下方的按钮文本,点击可进入打印
zIndex: 20002, // 预览窗口的z-index,默认是20002,最好比默认值更高
previewBeforeOpenCallback () {
console.log('正在加载预览窗口!');
console.log(that.msg, this)
}, // 预览窗口打开之前的callback
previewOpenCallback () {
console.log('已经加载完预览窗口,预览打开了!')
}, // 预览窗口打开时的callback
beforeOpenCallback () {
console.log('开始打印之前!')
}, // 开始打印之前的callback
openCallback () {
console.log('执行打印了!')
}, // 调用打印时的callback
closeCallback () {
console.log('关闭了打印工具!')
}, // 关闭打印的callback(无法区分确认or取消)
clickMounted () {
console.log('点击v-print绑定的按钮了!')
},
// url: 'http://localhost:8080/', // 打印指定的URL,确保同源策略相同
// asyncUrl (reslove) {
// setTimeout(() => {
// reslove('http://localhost:8080/')
// }, 2000)
// },
}
}
},
}
打印时发现,打印的效果不是想要的,或者表格边框线显示不全,使用媒体查询设置打印的样式
<style media="print" lang="scss">
// 修改页边距
@page {
//size: auto;
//margin: 3mm;
}
// 媒体查询, 打印时修改样式
@media print {
.el-table{
border: 3px solid #606060;
}
.el-table__header-wrapper {
border-bottom: 3px solid #606060;
}
.el-table > .el-table__header-wrapper > .el-table__header > thead > tr > th{
border-right: 3px solid #606060 !important;
}
.el-table > .el-table__body-wrapper > .el-table__body > tbody > .el-table__row > td{
border-bottom: 3px solid #606060 !important;
border-right: 3px solid #606060 !important;
}
}
</style>