vue3简单打印实现(新测试:vue2打印原理相同)

需求
vue3+ts+vite
重要:灵感来源大佬总结

主要实现原理
window.print()方法调起浏览器打印
规避页面重新赋值用以解决页面在打印后按键失效问题

上代码

const handlePrint = () =>{
      editableIs.value = false;
      showChang.value =true;//以上用于关闭不需要打印的部分 最简单的方法是给dom v-if,不需要赘述吧
      setTimeout(function(){//双向绑定需要给页面渲染时间,延迟一定时间
        let oldStr = window.document.body.innerHTML; // 获取body的内容
      let start = "<!--startprint-->"; // 开始打印标识, 17个字符
      let end = "<!--endprint-->"; // 结束打印标识
      let newStr = oldStr.substr(oldStr.indexOf(start) + 17); // 截取开始打印标识之后的内容
      newStr = newStr.substring(0, newStr.indexOf(end)); // 截取开始打印标识和结束打印标识之间的内容
      let printData = newStr
      printHtml(printData)
      },500)
}

注意配合打印后的回调

window.onafterprint = function(event) {
      //放开隐藏的元素
      editableIs.value = true;
      showChang.value =false;
};

这里是需要引入的printHtml方法

export default function printHtml(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);
  });
}
 
// 设置打印样式
function getStyle() {
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;
}
 
// 清空打印内容
function cleanPrint() {
  let div = document.getElementById('print-container')
  if (!!div) {
    document.querySelector('body').removeChild(div)
  }
}
 
// 新建DOM,将需要打印的内容填充到DOM
function getContainer(html) {
  cleanPrint()
  let container = document.createElement("div");
  container.setAttribute("id", "print-container");
  container.innerHTML = html;
  return container;
}
 
// 图片完全加载后再调用打印方法
function getLoadPromise(dom) {
  let imgs = dom.querySelectorAll("img");
  imgs = [].slice.call(imgs);
 
  if (imgs.length === 0) {
    return Promise.resolve();
  }
 
  let finishedCount = 0;
  return new Promise(resolve => {
    function check() {
      finishedCount++;
      if (finishedCount === imgs.length) {
        resolve();
      }
    }
    imgs.forEach(img => {
      img.addEventListener("load", check);
      img.addEventListener("error", check);
    })
  });
}

防止还有看不懂的

import printHtml from "../../utils/print" //找个文件夹丢进去 引入

问题
打印缺少css样式 :目前已符合项目需求,需要的话可以在封装方法中引入css

优势还是挺大的,避免了转图片再打印时的dom切割问题

上个图
在这里插入图片描述

再次感谢大佬
https://blog.csdn.net/qq_38128179/article/details/103344021

补充:
在vite打包后页面中注释内容会被删除-----使用无意义的标签如"<i v-if=“colse” name=“test"> < v-if=“colse” i>"进行包裹,调整切割位数就可以了,注意v-if的时机

vue2

// dom部分 可用if控制
<i test='name'></i>
<div>
    打印测试测测测测测测测测测
</div>
<i test='names'></i>
methods: {
        handlePrint() {
            setTimeout(function(){//双向绑定需要给页面渲染时间,延迟一定时间
            //以下可替换为newStr = document.getElementById("print").innerHTML 
            let oldStr = window.document.body.innerHTML; // 获取body的内容
            console.log(oldStr)
            let start = '<i test="name">'; // 开始打印标识, 19个字符 注意""
            let end = '<i test="names"></i>'; // 结束打印标识
            let newStr = oldStr.substr(oldStr.indexOf(start) + 19); // 截取开始打印标识之后的内容
            newStr = newStr.substring(0, newStr.indexOf(end)); // 截取开始打印标识和结束打印标识之间的内容
            let printData = newStr
            console.log(newStr)
            printHtml(printData)
            },1000)
}
    },

补充一下canvas打印发放—echarts
原理:将canvas转为图片 ,替换本页的画布为图片,注这里为打印弹窗区域内容,而不需要将原本内容替换回来只需要在打印时关闭弹窗,就相当于刷新了弹窗

            <div id="print">
                <!-打印内容 canvas的包裹标签上加标识testCharts->
            </div>



        handlePrint() {
            this.dialogVisible = true;
            let newStr="";
            // setTimeout(function () {//双向绑定需要给页面渲染时间,延迟一定时间
            let cvs = document.getElementsByTagName("canvas");
            let resImgs = document.getElementsByClassName("testCharts");
            for(let i = 0;i<resImgs.length;i++){
                let context = cvs[0].getContext("2d");
                let img = new Image();
                let strDataURL = cvs[0].toDataURL("image/png");
                img.src = strDataURL;
                resImgs[i].innerHTML = `<img src="${strDataURL}">`;
            }
            newStr = document.getElementById("print").innerHTML;//置换完图片获取页面
            // }, 1000)
            setTimeout(()=>{
                this.dialogVisible = false;
                printHtml(newStr);
            },1000)
        }
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值