Vue-cli 中的打印功能(window.print)
print.js 的封装
export default {
initIframe(printOption) {
let printIframe = document.getElementById('easyPrintIframe');
if (!printIframe) {
printIframe = document.createElement('iframe');
printIframe.id = 'easyPrintIframe';
printIframe.style.position = 'fixed';
printIframe.style.width = '0';
printIframe.style.height = '0';
printIframe.style.top = '-100px';
if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) {
printIframe.src =
'javascript:document.write("<head><script>document.domain="' + document.domain + '";</script></head><body></body>")';
}
document.body.appendChild(printIframe);
printIframe.onload = () => {
this.getStyle(printOption);
};
}else{
printIframe.contentDocument.body.innerHTML = '';
printIframe.contentDocument.head.innerHTML = '';
this.getStyle(printOption);
}
},
setValues () {
const inputs = document.querySelectorAll('input');
const textareas = document.querySelectorAll('textarea');
const selects = document.querySelectorAll('select');
for(let i = 0; i < inputs.length; i++) {
if (inputs[i].type === "checkbox" || inputs[i].type === "radio") {
if (inputs[i].checked === true) {
inputs[i].setAttribute('checked', "checked")
} else {
inputs[i].removeAttribute('checked');
}
} else if (inputs[i].type === "text") {
inputs[i].setAttribute('value', inputs[i].value)
}
}
for(let i = 0; i < textareas.length; i++) {
textareas[i].setAttribute('value', textareas[i].value);
}
for(let i = 0; i < selects.length; i++) {
if (selects[i].type === 'select-one') {
let child = selects[i].children;
for (let j in child) {
if (child[j].tagName === 'OPTION') {
if (child[j].selected === true) {
child[j].setAttribute('selected', "selected")
} else {
child[j].removeAttribute('selected')
}
}
}
}
}
},
getStyle(printOption) {
const printIframe = document.getElementById('easyPrintIframe');
let styleList = '',
styleTagList = document.querySelectorAll('style');
for (let i = 0; i < styleTagList.length; i++) {
styleList += styleTagList[i].outerHTML;
}
printIframe.contentDocument.head.innerHTML = styleList;
let linkTagList = document.querySelectorAll('link');
for (let i = 0; i < linkTagList.length; i++) {
let link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
if(styles[i].type) link.setAttribute('type', styles[i].type);
else link.setAttribute('type', 'text/css');
link.setAttribute('href', styles[i].href);
link.setAttribute('media','all');
printIframe.contentDocument.head.appendChild(link);
}
let printOptionStyle = document.createElement('style');
printOptionStyle.innerHTML = '@media print {' + printOption + '}';
printIframe.contentDocument.head.appendChild(printOptionStyle);
},
print(context, printOption = '') {
this.initIframe(printOption);
const $iframe = document.getElementById("easyPrintIframe");
$iframe.contentDocument.body.innerHTML = context.$el.outerHTML;
context.$nextTick(() => {
setTimeout(() => {
$iframe.contentWindow.focus();
try {
if (!$iframe.contentWindow.document.execCommand('print', false, null)) {
$iframe.contentWindow.print();
WebBrowser.ExecWB(7, 1);
}
} catch (e) {
$iframe.contentWindow.print();
WebBrowser.ExecWB(7, 1 );
}
$iframe.contentWindow.close();
}, 100);
});
}
}
使用
import Println from 'print.js'
...
created() {
Println.print(this, print(this, `
@page { size: portrait; color: #f00}
.hello {transform: scale(1.0);}
`);
}
...
说明
打印其实并不是连打印机打印,而是将网页保存成 PDF, 然后用电脑连接打印机打印。
可以将 print.js 导入某个组件使用,也可以绑定给 Vue 原型。
调用打印时传的参数,第一个是要打印的 Vue 组件,第二是打印时的样式设置,至于还可以做哪些设置,可以去官网看(页眉,页脚,纸张大小等都可以设置)。
打印的步骤
- 创建 iframe 标签
- 获取要打印的组件中的样式,添加给 iframe
- 打印
调用示例里传的打印样式设置的参数中,size 可以确定预览的横竖屏模式,scale 可以设置打印的比例。
在 setValues
函数中之所以要对表单项重新赋值是因为 Vue
中的表单项的值是通过 v-model
绑定的,直接打印时读不到这个值,需要通过 JS
读取值并重新设置 value
属性。
有时候需要分页打印,分页打印要么就是内容太多自动分页,要是自己控制分页的话,需要将每页的内容单独放在独立的标签中,然后通过标签样式控制,让其打印时自动分页。
...
<style>
.page {
page-break-after: always;
}
</style>
...
<div class="page">第一页</div>
<div class="page">第二页</div>
<div class="page">第三页</div>
...