3

今天遇到一个需求,看起来也比较简单,就是实现一个打印功能。页面中有一个表单,将表单里的数据对应添加到表格中,然后点击打印按钮,实现预览打印,这里我用的是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'
            }

          ]
        }
    }
})


运行效果如下图所示:

图片描述
图片描述

当然如果有大佬知道还有更好的办法,希望指点一下,也希望此文能帮助遇到此坑的人。另外第一次写文章,如有排版等不好,敬请谅解。


夕水
5.2k 声望5.7k 粉丝

问之以是非而观其志,穷之以辞辩而观其变,资之以计谋而观其识,告知以祸难而观其勇,醉之以酒而观其性,临之以利而观其廉,期之以事而观其信。