0


vue中实现打印功能的几种方法

1、直接调用 window.print()方法

这种方法默认打印整个页面,不能打印局部页面。并且不保留原有样式

<!doctype html><html><head><meta charset="utf-8"><title>打印测试页</title><style type="text/css"
           media="screen">.pageheader,.pagefooter {display: none;}</style><style type="text/css"
           media="print">/*每一页 如果没有另外自定义的话 */
        @page {
            margin-left: 50px;
            margin-top: 100px;}/*第一页*/
        @page :first {
            margin-left:50%;
            margin-top:50%;}/*分页标记*/.geovindu {
            page-break-after: always;}.pageheader {
            margin-top: 10px;
            font-size: 12pt;}.pagefooter {
            margin-top: 10px;
            font-size: 10pt;}</style></head><body><script type="text/javascript">functionmain(){
            window.print();}</script><div id="geovindu"class="geovindu"><div class="pageheader">页眉:打印测试</div><div class="conent">
            封面内容
        </div><div class="pagefooter">页脚:第1页/共2页</div></div><div id="geovindu"class="geovindu"><div class="pageheader">页眉:打印测试</div><div class="conent">
            第二页内容
        </div><div class="pagefooter">页脚:第2页/共2页</div></div><button onclick="main()">打印按钮</button></body></html>

2、自定义封装打印方法

这种方法也是调用了原生打印,通过封装好方法,可以指定需要打印的区域,自由度高,缺点就是通过截取全页面的html进行字符串截取,并且不保留原有样式,需要去手动添加样式。

2.1、封装打印方法,创建一个printHtml.js文件

exportdefaultfunctionprintHtml(html){let style =getStyle();let container =getContainer(html);

    document.body.appendChild(style);
    document.body.appendChild(container);getLoadPromise(container).then(()=>{
        window.print();
        document.body.removeChild(style);
        document.body.removeChild(container);});}// 设置打印样式functiongetStyle(){let styleContent =`#print-container {
      display: none;
  }
  @media print {
      body > :not(.print-container) {
          display: none;
      }
      html,
      body {
          display: block !important;
      }
      #print-container {
          display: block;
      }
  }`;let style = document.createElement("style");
    style.innerHTML = styleContent;return style;}// 清空打印内容functioncleanPrint(){let div = document.getElementById('print-container')if(!!div){
        document.querySelector('body').removeChild(div)}}// 新建DOM,将需要打印的内容填充到DOMfunctiongetContainer(html){cleanPrint()let container = document.createElement("div");
    container.setAttribute("id","print-container");
    container.innerHTML = html;return container;}// 图片完全加载后再调用打印方法functiongetLoadPromise(dom){let imgs = dom.querySelectorAll("img");
    imgs =[].slice.call(imgs);if(imgs.length ===0){returnPromise.resolve();}let finishedCount =0;returnnewPromise(resolve =>{functioncheck(){
            finishedCount++;if(finishedCount === imgs.length){resolve();}}
        imgs.forEach(img =>{
            img.addEventListener("load", check);
            img.addEventListener("error", check);})});}

2.2、使用方式

<template><div><button @click="onPrint">打印1</button>// dom部分 可用if控制<i test='printStart'></i><div v-show="oldStr">
            v-show1的
        </div><div v-show="oldStr">
            v-show2的
        </div>
        测试冲冲冲
        <div class="xwtable"><table><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>手机</th><th>邮箱</th><th>地址</th><th>工龄</th><th>岗位</th><th>薪资</th></tr><tr v-for="(item, index) in list"
                    key="index"><td>{{ index +1}}</td><td>{{ item.name }}</td><td>{{ item.age }}</td><td>{{ item.sex }}</td><td>{{ item.phone }}</td><td>{{ item.mail }}</td><td>{{ item.address }}</td><td>{{ item.workAge }}</td><td>{{ item.jobs }}</td><td>{{ item.salary }}</td></tr></table></div><i test='printEnt'></i><div><div class="text_styte">我是测试样式的</div></div></div></template><script setup lang="ts">// 引入封装好的打印函数import printHtml from"./printHtml.js";import{ ref }from'vue';let oldStr =ref(false);let editableIs =ref(true);let showChang =ref(true);let list =[{
    name:"阿哒",
    age:26,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:2,
    jobs:"研发",
    salary:"1.8k"},{
    name:"阿荣",
    age:24,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:1,
    jobs:"研发",
    salary:"1.8k"},{
    name:"阿豪",
    age:26,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:5,
    jobs:"产品",
    salary:"1.8k"},{
    name:"阿晨",
    age:29,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:9,
    jobs:"设计",
    salary:"1.8k"},{
    name:"阿震",
    age:30,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:7,
    jobs:"销售",
    salary:"1.8k"},{
    name:"阿锋",
    age:21,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:0.1,
    jobs:"售后",
    salary:"1.8k"}]// 点击处理打印constonPrint=()=>{
  editableIs.value =false;//以上用于关闭不需要打印的部分 最简单的方法是给dom v-if,不需要赘述吧
  showChang.value =true;//双向绑定需要给页面渲染时间,延迟一定时间setTimeout(function(){// document.title = '标题 | 这是页眉标题哦';// 获取body的内容let oldStr = window.document.body.innerHTML;// 开始打印标识, 21个字符 注意""let start ='<i test="printStart">';// 结束打印标识, 23个字符let end ='<i test="printEnt"></i>';let condition =truelet printData =''while(condition){if(oldStr.indexOf(start)==-1){
        condition =false}else{// 截取开始打印标识之后的内容let newStr = oldStr.substr(oldStr.indexOf(start)+21);// 截取开始打印标识和结束打印标识之间的内容
        printData = printData + newStr.substring(0, newStr.indexOf(end));// 截取结束打印标识之后的内容
        oldStr = newStr.substr(newStr.indexOf(end)+23);}}let reg =newRegExp("display: none","g");//定义正则表达式
    printData = printData.replace(reg,'')// 调用打印printHtml(printData)},500)}</script><style scoped>.xwtable {
    width:100%;
    border-collapse: collapse;
    border: 1px solid #ccc;}.xwtable thead td {
    font-size: 12px;
    color: #333333;
    text-align: center;
    background:url(table_top.jpg) repeat-x top center;
    border: 1px solid #ccc;
    font-weight: bold;}.xwtable tbody tr {
    background: #fff;
    font-size: 12px;
    color: #666666;}.xwtable tbody tr.alt-row {
    background: #f2f7fc;}.xwtable td {
    line-height: 20px;
    text-align: left;
    padding: 4px 10px 3px 10px;
    height: 18px;
    border: 1px solid #ccc;}</style>

3、使用vue3-print-nb依赖

这个方法可以自定义打印区域,并且保留原有样式,缺点是打印区域的样式不能和打印区域外的样式相关联。同事我们也可以在通过

@media print

来对需要打印的区域进行样式设置,自由度比较好一些,具体更多使用方式还是大家一起去发掘。

这里使用的是vue3+ts的引入和使用方式,vue2的引入方式可以去看看别的文章。

3.1、全局引入方式

// main.tsimport{ createApp }from"vue";import App from"./App.vue";import Print from'vue3-print-nb'createApp(App).use(Print).mount("#app");

3.2、局部引入方式(setup)自定义指令--------------(推荐)

网上有很多

<script lang="ts">

或者

<script>

的使用自定义指令的方式这里就不再赘述了。

<script setup lang="ts">import print from'vue3-print-nb'// 使用自定义指令const vPrint = print

let prints ={
  id:'print-iframe',
  popTitle:'配置页眉标题',// 打印配置页上方的标题
  extraHead:'',// 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
  preview:false,// 是否启动预览模式,默认是false
  previewTitle:'预览的标题',// 打印预览的标题
  previewPrintBtnLabel:'预览结束,开始打印',// 打印预览的标题下方的按钮文本,点击可进入打印
  zIndex:20002,// 预览窗口的z-index,默认是20002,最好比默认值更高previewBeforeOpenCallback(){console.log('正在加载预览窗口!');},// 预览窗口打开之前的callbackpreviewOpenCallback(){console.log('已经加载完预览窗口,预览打开了!')},// 预览窗口打开时的callback// 开始打印之前的callbackbeforeOpenCallback(){console.log('开始打印之前!')},openCallback(){console.log('执行打印了!')},// 调用打印时的callbackcloseCallback(){console.log('关闭了打印工具!');var element = document.getElementById("print-iframe"); element?.parentNode?.removeChild(element);},// 关闭打印的callback(无法区分确认or取消)clickMounted(){console.log('点击v-print绑定的按钮了!')},
  standard:'',
  extarCss:''}</script>

3.3、简单直接使用场景

我们在需要打印的html标签上添加在

prints

对象里定义的id属性 ,通过在按钮加上

v-print="prints"

自定义指令实现打印。

<template><button v-print="prints">打印2</button><div id="print-iframe">// dom部分 可用if控制<div class="xwtable"><table><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>手机</th><th>邮箱</th><th>地址</th><th>工龄</th><th>岗位</th><th>薪资</th></tr><tr v-for="(item, index) in list"
                    key="index"><td>{{ index +1}}</td><td>{{ item.name }}</td><td>{{ item.age }}</td><td>{{ item.sex }}</td><td>{{ item.phone }}</td><td>{{ item.mail }}</td><td>{{ item.address }}</td><td>{{ item.workAge }}</td><td>{{ item.jobs }}</td><td>{{ item.salary }}</td></tr></table></div><div><div class="text_styte">我是测试样式的</div></div></div></template><script setup lang="ts">// 引入封装好的打印函数import print from'vue3-print-nb'import{ ref }from'vue';const vPrint = print
let prints ={
  id:'print-iframe',
  popTitle:'配置页眉标题',// 打印配置页上方的标题
  extraHead:'',// 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
  preview:false,// 是否启动预览模式,默认是false
  previewTitle:'预览的标题',// 打印预览的标题
  previewPrintBtnLabel:'预览结束,开始打印',// 打印预览的标题下方的按钮文本,点击可进入打印
  zIndex:20002,// 预览窗口的z-index,默认是20002,最好比默认值更高previewBeforeOpenCallback(){console.log('正在加载预览窗口!');},// 预览窗口打开之前的callbackpreviewOpenCallback(){console.log('已经加载完预览窗口,预览打开了!')},// 预览窗口打开时的callback// 开始打印之前的callbackbeforeOpenCallback(){console.log('开始打印之前!')},openCallback(){console.log('执行打印了!')},// 调用打印时的callbackcloseCallback(){console.log('关闭了打印工具!');var element = document.getElementById("print-iframe"); element?.parentNode?.removeChild(element);},// 关闭打印的callback(无法区分确认or取消)clickMounted(){console.log('点击v-print绑定的按钮了!')},
  standard:'',
  extarCss:''}let list =[{
    name:"阿哒",
    age:26,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:2,
    jobs:"研发",
    salary:"1.8k"},{
    name:"阿荣",
    age:24,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:1,
    jobs:"研发",
    salary:"1.8k"},{
    name:"阿豪",
    age:26,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:5,
    jobs:"产品",
    salary:"1.8k"},{
    name:"阿晨",
    age:29,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:9,
    jobs:"设计",
    salary:"1.8k"},{
    name:"阿震",
    age:30,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:7,
    jobs:"销售",
    salary:"1.8k"},{
    name:"阿锋",
    age:21,
    sex:"男",
    phone:"12345678901",
    mail:"[email protected]",
    address:"蓝星星国马尔哈哈海岛",
    workAge:0.1,
    jobs:"售后",
    salary:"1.8k"}]// 点击处理打印</script><style scoped>.xwtable {
    width:100%;
    border-collapse: collapse;
    border: 1px solid #ccc;}.xwtable thead td {
    font-size: 12px;
    color: #333333;
    text-align: center;
    background:url(table_top.jpg) repeat-x top center;
    border: 1px solid #ccc;
    font-weight: bold;}.xwtable tbody tr {
    background: #fff;
    font-size: 12px;
    color: #666666;}.xwtable tbody tr.alt-row {
    background: #f2f7fc;}.xwtable td {
    line-height: 20px;
    text-align: left;
    padding: 4px 10px 3px 10px;
    height: 18px;
    border: 1px solid #ccc;}</style>

3.4、在打印前处理需要打印的内容区域

  1. 在触发打印前我们需要做一些事情,我们可以通过创建两个button标签点击触发处理事件后在执行打印功能。
  2. 并且我们也可以创建一个新的dom节点去存放相要打印的内容,重新渲染到页面上再执行打印。
<template><div><button ref="printRef" v-print="prints">打印2</button><button @click="onClick">打印3</button><div id="printArea"><div class="text_styte">我是测试样式的</div><Auto></Auto></div></div></template><script setup lang="ts">import Auto from"./Auto.vue";import print from'vue3-print-nb'import{ ref }from'vue';const vPrint = print
let printRef =ref();let prints ={
  id:'print-iframe',
  popTitle:'配置页眉标题',// 打印配置页上方的标题
  extraHead:'',// 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
  preview:false,// 是否启动预览模式,默认是false
  previewTitle:'预览的标题',// 打印预览的标题
  previewPrintBtnLabel:'预览结束,开始打印',// 打印预览的标题下方的按钮文本,点击可进入打印
  zIndex:20002,// 预览窗口的z-index,默认是20002,最好比默认值更高previewBeforeOpenCallback(){console.log('正在加载预览窗口!');},// 预览窗口打开之前的callbackpreviewOpenCallback(){console.log('已经加载完预览窗口,预览打开了!')},// 预览窗口打开时的callback// 开始打印之前的callbackbeforeOpenCallback(){console.log('开始打印之前!')},openCallback(){console.log('执行打印了!')},// 调用打印时的callbackcloseCallback(){console.log('关闭了打印工具!');var element = document.getElementById("print-iframe"); element?.parentNode?.removeChild(element);},// 关闭打印的callback(无法区分确认or取消)clickMounted(){console.log('点击v-print绑定的按钮了!')},
  standard:'',
  extarCss:''}constonClick=()=>{test()
  printRef.value.click()}consttest=()=>{let iframe = document.createElement("div");
  iframe.setAttribute("id","print-iframe");
  iframe.setAttribute("style","width: 100%; height: 100%;  z-index: -9999; border: 0; margin: 0; padding: 0; ");// 创建节点
  document.body.appendChild(iframe);//获取目标节点let targetDom = document.getElementById("printArea");console.log(targetDom);let temp =`<div class="text_styte">我是测试样式的22222222222</div> <div id="pageFooter">Page </div>`;
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  temp += targetDom?.innerHTML
  iframe.innerHTML = temp
}</script>

本篇文章主要介绍如何使用,文笔描述不好,大家见谅。。。


本文转载自: https://blog.csdn.net/weixin_44982333/article/details/127609629
版权归原作者 Rime· 所有, 如有侵权,请联系我们删除。

“vue中实现打印功能的几种方法”的评论:

还没有评论