今天遇到一个需求,看起来也比较简单,就是实现一个打印功能。页面中有一个表单,将表单里的数据对应添加到表格中,然后点击打印按钮,实现预览打印,这里我用的是iview框架,如下图所示:
实现打印的功能,很明显就要用到window.print()方法,但是如果不做限制,那么这个方法就会将页面内的所有内容给打印出来,这肯定是不满足需求的。有两种方法来实现,一种是利用CSS的媒体查询,另一种则是使用js。
我这里采用的是第一种办法,我在stackoverflow上大致搜了一下,曾经有人问过打印的问题。如下图所示:
总的说来,实现打印的方式也无非就是这两种方法,当然这也不排除使用插件,我看了下回答,有一个利用jquery封装的插件,大致去看了下这个插件,也并没有达到我的要求,而且代码调用传的参数也有些多,索性我就放弃了。想要了解这个插件的可以前往这个网址:[https://github.com/jasonday/p...]
首先说下为什么用js方式实现打印不行,因为在这个系统当中,我写了好几个样式文件,如果使用js方式来实现打印,那么就势必要引入多个css,而且css文件还不好引入,这是其一,其二就是还要操作DOM取得要打印的内容。以下是js实现打印的具体代码:
function Print(el){
var mywindow = window.open('', '', 'height=800,width=1000');
mywindow.document.write('<html><head><title>' + document.title + '</title>');
mywindow.document.write('</head><body >');
mywindow.document.write('<h1>' + document.title + '</h1>');
//代码的着重点就在此处
mywindow.document.write(document.getElementById(el).innerHTML);
mywindow.document.write('</body></html>');
mywindow.document.close(); // necessary for IE >= 10
mywindow.focus(); // necessary for IE >= 10*/
mywindow.print();
mywindow.close();
return true;
}
所以我索性采用了第二种方法,就是利用css媒体查询,css专门有个与打印有关的媒体查询,代码结构如下:
@media print{
//具体代码
}
我们只需要将不打印的元素的display属性设置为none,打印的元素的display属性设置为block即可。这个代码里还涉及到设置元素宽度的单位,目前我只知道有cm和mm。另外还有一个@page属性设置,想了解该属性可自行百度。有人曾说有一个最简便的办法就是在媒体查询里面这样写:
@media print{
*{
display:none;
}
#myPrint{
display:block;
}
}
我不知道他是怎么运行出效果的,但至少我是没有成功,我只能通过给不需要打印的元素添加样式类noprint,给需要打印的元素加样式类print。像如下这样:
<div class="noprint">//这里是不打印的区域</div>
<div class="print">//这里是打印的区域</div>
然后css就这样写:
@media print{
.noprint{
display:none;
}
.print{
display:block;
}
}
值得注意的就是如果页面中有元素没有设置display:none,而且它又在页面中没有视觉显示,但是却有定位属性,就需要将它的定位属性给去掉,如下图所示:
我的按钮代码大致是这样的:
我利用iview的table组件来作为打印的元素,如下图所示:
printHead和printData就是要打印的数据,print方法里面我是如此写的:
print() {
this.printHead = [
{
title: "企业/团队名称",
key: 'client_name'
},
{
title: "法人/负责人",
key: 'lp_name'
},
{
title: "团队人数",
key: 'number_of_employees'
},
{
title: "联系电话",
key: 'contact_information'
},
{
title: "QQ/微信",
key: 'qq_we_chat'
},
{
title: "注册地址",
key: 'registered_address'
},
{
title: "成立时间",
key: 'time_of_establishment'
},
{
title: "审核状态",
key: 'status'
},
{
title: "申请时间",
key: 'created_time'
},
{
title: "经营简介",
key: 'enterprise_introduction'
},
{
title: "审核意见",
key: 'reason'
}
];
this.printData = [];
this.printData.push(this.curAudit);
this.printing = true;
setTimeout(function(){
window.print();
},1000)
},
这里我想大概是因为页面在渲染iview组件的原因,所以必须要延迟运行打印方法window.print()才会真正执行到打印功能。但是我却碰到一个很奇怪的问题,如下图所示:
这个问题足足困扰了我一下午,我一下午都在想为什么会出现这样的结果,后来我终于明白了,是iview的样式布局造成的,iview的底层用了两个table元素来封装这个表格组件,我没办法,只好选择不用iview的table组件,自己手写table元素以及样式(如果有更好的方法希望有大佬指点迷津)。为此我还特意写了一个demo来测试,测试代码如下:
页面需要引入:
<link rel="stylesheet" type="text/css" href="http://unpkg.com/iview/dist/styles/iview.css">
<script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>
<script type="text/javascript" src="http://unpkg.com/iview/dist/iview.min.js"></script>
css:
.noprint{
display: block;
margin:20px auto;
}
.table{
width: 100%;
}
.table th,.table td{
text-align: center;
}
@media print{
.noprint{
display: none;
}
.print{
display: block;
}
}
html:
<div id="app">
<div class="table">
<i-Table :columns="columns1" :data="data1" id="print"></i-Table>
</div>
<i-button type="primary" @click="window.print()" class="noprint">打印</i-button>
</div>
js:
new Vue({
el: '#app',
data(){
return {
columns1: [
{
title: 'Name',
key: 'name'
},
{
title: 'Age',
key: 'age'
},
{
title: 'Address',
key: 'address'
},
{
title: 'date',
key: 'date'
}
],
data1: [
{
name: 'John Brown',
age: 18,
address: 'New York No. 1 Lake Park',
date: '2016-10-03'
},
{
name: 'Jim Green',
age: 24,
address: 'London No. 1 Lake Park',
date: '2016-10-01'
},
{
name: 'Joe Black',
age: 30,
address: 'Sydney No. 1 Lake Park',
date: '2016-10-02'
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
date: '2016-10-04'
}
]
}
}
})
运行效果如下图所示:
当然如果有大佬知道还有更好的办法,希望指点一下,也希望此文能帮助遇到此坑的人。另外第一次写文章,如有排版等不好,敬请谅解。