在vue项目开发过程中,有遇到打印的问题时,直接打印就会把系统的菜单栏和导航栏面包屑全部都打印出来,所以要想只打印页面部分我总结了两种办法:
第一种方法:
一般情况我都是通过window.open()直接打开一个需要打印的页面路径,这样就会在浏览器上新增一个标签,这个浏览器标签里就是单纯的需要打印的页面,没有菜单栏和导航栏面包屑等不需要打印的东西,然后在页面里直接window.print()来调取浏览器的打印窗口就ok了,这种方法需要注意的地方是,要把需要打印的菜单的路径在routers.js路由菜单里再配置一遍。
代码如下:
{ path: '/print-aaa',
name: 'print-aaa',
meta: { title: '打印-aaa', hideInMenu: true },
component: () => import ('@/view/aaa')
},
这样打印时直接
window.open(`/print-aaa`)
就可以实现新打开浏览器页签打印。
第二种方法:
不打开浏览器页签直接在当前页签下实现打印页面的一部分
首先封装一个打印的公共方法,并定义全局实例:$print
prints/print.js
github 地址:https://github.com/xyl66/vuePlugs_printjs/blob/master/print.js
// 打印类属性、方法定义
/* eslint-disable */
const Print=function(dom,options){
if(!(thisinstanceofPrint)) return new Print(dom,options);
this.options=this.extend({
'noPrint':'.no-print'
},options);
if((typeofdom)==="string"){
this.dom=document.querySelector(dom);
}else{
this.isDOM(dom)
this.dom=this.isDOM(dom)?dom:dom.$el;
}
this.init();
};
Print.prototype={
init:function(){
var content=this.getStyle()+this.getHtml();
this.writeIframe(content);
},
extend:function(obj,obj2){
for(varkinobj2){
obj[k]=obj2[k];
}
return obj;
},
getStyle:function(){
var str="",
styles=document.querySelectorAll('style,link');
for(var i=0;i<styles.length;i++){
str+=styles[i].outerHTML;
}
str+="<style>"+(this.options.noPrint?this.options.noPrint:'.no-print')+"{display:none;}</style>";
returnstr;
},
getHtml:function(){
var inputs=document.querySelectorAll('input');
var textareas=document.querySelectorAll('textarea');
var selects=document.querySelectorAll('select');
for(var k=0;k<inputs.length;k++){
if(inputs[k].type=="checkbox"||inputs[k].type=="radio"){
if(inputs[k].checked==true){
inputs[k].setAttribute('checked',"checked")
}else{
inputs[k].removeAttribute('checked')
}
}else if(inputs[k].type=="text"){
inputs[k].setAttribute('value',inputs[k].value)
}else{
inputs[k].setAttribute('value',inputs[k].value)
}
}
for(var k2=0;k2<textareas.length;k2++){
if(textareas[k2].type=='textarea'){
textareas[k2].innerHTML=textareas[k2].value
}
}
for(var k3=0;k3<selects.length;k3++){
if(selects[k3].type=='select-one'){
var child=selects[k3].children;
for(var i in child){
if(child[i].tagName=='OPTION'){
if(child[i].selected==true){
child[i].setAttribute('selected',"selected")
}else{
child[i].removeAttribute('selected')
}
}
}
}
}
// 包裹要打印的元素
// fix: https://github.com/xyl66/vuePlugs_printjs/issues/36
letouterHTML=this.wrapperRefDom(this.dom).outerHTML
return outerHTML;
},
// 向父级元素循环,包裹当前需要打印的元素
// 防止根级别开头的 css 选择器不生效
wrapperRefDom:function(refDom){
let prevDom=null
let currDom=refDom
// 判断当前元素是否在 body 中,不在文档中则直接返回该节点
if(!this.isInBody(currDom)) return currDom
while(currDom){
if(prevDom){
letelement=currDom.cloneNode(false)
element.appendChild(prevDom)
prevDom=element
}else{
prevDom=currDom.cloneNode(true)
}
currDom=currDom.parentElement
}
return prevDom
},
writeIframe:function(content){
var w,doc,iframe=document.createElement('iframe'),
f=document.body.appendChild(iframe);
iframe.id="myIframe";
//iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
iframe.setAttribute('style','position:absolute;width:0;height:0;top:-10px;left:-10px;');
w=f.contentWindow||f.contentDocument;
doc=f.contentDocument||f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();
var _this=this
iframe.onload=function(){
_this.toPrint(w);
setTimeout(function(){
document.body.removeChild(iframe)
},100)
}
},
toPrint:function(frameWindow){
try{
setTimeout(function(){
frameWindow.focus();
try{
if(!frameWindow.document.execCommand('print',false,null)){
frameWindow.print();
}
}catch(e){
frameWindow.print();
}
frameWindow.close();
},10);
}catch(err){
console.log('err',err);
}
},
// 检查一个元素是否是 body 元素的后代元素且非 body 元素本身
isInBody:function(node){
return (node===document.body)?false:document.body.contains(node);
},
isDOM:(typeofHTMLElement==='object')?
function(obj){
return objinstanceofHTMLElement;
}:
function(obj){
return obj&&typeofobj==='object'&&obj.nodeType===1&&typeofobj.nodeName==='string';
}
};
const MyPlugin={}
MyPlugin.install=function(Vue,options){
// 4. 添加实例方法
Vue.prototype.$print=Print
}
export default MyPlugin
这样使用时只要把需要打印的div设置ref名就可以直接用以下代码
this.$print(this.$refs.需要打印的div的ref名)
示例:print.vue
<template>
<div ref="print">
打印内容
<div class="no-print">不要打印我</div>
<div>
</template>
main.js 引入插件
import Print from "@/prints/print"
Vue.use(Print) //注册
回到 print.vue
exprt default {
name:'Print_component',
methods:{
onPrint(){
this.$print(this.$refs.print) //使用
}
}
}