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

这篇具有很好参考价值的文章主要介绍了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">
         function main() {
            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文件

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);
        })
    });
}

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: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 2,
    jobs: "研发",
    salary: "1.8k"
},
{
    name: "阿荣",
    age: 24,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 1,
    jobs: "研发",
    salary: "1.8k"
},
{
    name: "阿豪",
    age: 26,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 5,
    jobs: "产品",
    salary: "1.8k"
},
{
    name: "阿晨",
    age: 29,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 9,
    jobs: "设计",
    salary: "1.8k"
},
{
    name: "阿震",
    age: 30,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 7,
    jobs: "销售",
    salary: "1.8k"
},
{
    name: "阿锋",
    age: 21,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 0.1,
    jobs: "售后",
    salary: "1.8k"
}
]
// 点击处理打印
const onPrint = () => {
  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 = true
    let 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 = new RegExp("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.ts
import { 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('正在加载预览窗口!'); }, // 预览窗口打开之前的callback
  previewOpenCallback() { console.log('已经加载完预览窗口,预览打开了!') }, // 预览窗口打开时的callback
  // 开始打印之前的callback
  beforeOpenCallback() {
    console.log('开始打印之前!')
  },
  openCallback() { console.log('执行打印了!') }, // 调用打印时的callback
  closeCallback() { 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('正在加载预览窗口!'); }, // 预览窗口打开之前的callback
  previewOpenCallback() { console.log('已经加载完预览窗口,预览打开了!') }, // 预览窗口打开时的callback
  // 开始打印之前的callback
  beforeOpenCallback() {
    console.log('开始打印之前!')

  },
  openCallback() { console.log('执行打印了!') }, // 调用打印时的callback
  closeCallback() { 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: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 2,
    jobs: "研发",
    salary: "1.8k"
},
{
    name: "阿荣",
    age: 24,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 1,
    jobs: "研发",
    salary: "1.8k"
},
{
    name: "阿豪",
    age: 26,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 5,
    jobs: "产品",
    salary: "1.8k"
},
{
    name: "阿晨",
    age: 29,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 9,
    jobs: "设计",
    salary: "1.8k"
},
{
    name: "阿震",
    age: 30,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    address: "蓝星星国马尔哈哈海岛",
    workAge: 7,
    jobs: "销售",
    salary: "1.8k"
},
{
    name: "阿锋",
    age: 21,
    sex: "男",
    phone: "12345678901",
    mail: "mmm@mmm.com",
    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('正在加载预览窗口!'); }, // 预览窗口打开之前的callback
  previewOpenCallback() { console.log('已经加载完预览窗口,预览打开了!') }, // 预览窗口打开时的callback
  // 开始打印之前的callback
  beforeOpenCallback() {
    console.log('开始打印之前!')

  },
  openCallback() { console.log('执行打印了!') }, // 调用打印时的callback
  closeCallback() { console.log('关闭了打印工具!'); var element = document.getElementById("print-iframe"); element?.parentNode?.removeChild(element); }, // 关闭打印的callback(无法区分确认or取消)
  clickMounted() { console.log('点击v-print绑定的按钮了!') },
  standard: '',
  extarCss: ''
}
const onClick = () => {
  test()
  printRef.value.click()
}
const test = () => {
  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://www.toymoban.com/news/detail-555562.html

到了这里,关于vue中实现打印功能的几种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaScript页面刷新的几种方法

    页面刷新是Web开发中常见的需求,它可以用于更新页面内容、重新加载数据或者重置用户界面。本文将介绍几种常见的JavaScript页面刷新方法,并提供相应的源代码示例。 使用location.reload()方法刷新页面: location.reload()方法用于重新加载当前页面。它会向服务器发送请求,获取

    2024年02月03日
    浏览(48)
  • JavaScript中数据过滤的几种方法

    JavaScript是一种广泛使用的编程语言,它提供了多种方法来对数据进行过滤。在本文中,我们将介绍JavaScript中常见的几种数据过滤方法,并提供相应的示例。 filter()方法是JavaScript数组对象的一个内置方法,它创建一个新数组,其中包含符合指定条件的所有元素。该方法接受一

    2024年02月04日
    浏览(61)
  • js几种打印方法

    printjs官网

    2024年02月11日
    浏览(29)
  • C/C++打印二维数组的几种方法(都进来给我补充!!!)

    1、双重for循环法: 2、一个for循环打印二维数组 3、利用指针数组来打印二维数组 4、指针数组打印二维数组第二版

    2024年02月09日
    浏览(32)
  • JavaScript中 判断网络状态的几种方法

    1. 使用 Navigator onLine 属性 Navigator onLine 属性判断浏览器是否在线,在线返回 true,离线返回 false; Navigator onLine 是只读属性,所有主流浏览器都支持 onLine 属性; 2. 使用 ononline、onoffline 事件 这两个方法属于 “侦听器”,在网络连接 / 断开的瞬间会触发(当网络从离线变为在

    2024年01月24日
    浏览(49)
  • 使用JavaScript关闭浏览器窗口的几种方法

    在Web开发中,有时候我们需要通过JavaScript来控制用户的浏览器行为,其中之一就是关闭浏览器窗口。本文将介绍几种使用JavaScript关闭浏览器窗口的方法,并提供相应的源代码示例。 使用window.close方法关闭窗口 要关闭当前窗口,可以使用window.close方法。这个方法会关闭当前浏

    2024年02月04日
    浏览(72)
  • JavaScript判断对象是否为空对象的几种方法

    目录 1、空对象对应的字符串为 \\\"{}\\\" 2、for in 3、jquery 的 isEmptyObject()方法 4、Object.getOwnPropertyNames() 5、ES6 的 Object.keys() JSON.stringify()扩展 1、第一大特性 小结 2、第二大特性 3、第三大特性 4、第四大特性 5、第五大特性 6、第六大特性 7、第七大特性 8、第八大特性 var data = {}; v

    2024年01月16日
    浏览(87)
  • JS数组求和的几种方法

    这篇文章主要介绍了JS数组求和的几种常用方法 方法一:通过原型对象扩展内置对象方法(即给Array增加方法) 方法二:普通for循环函数求和 方法三:使用递归 方法四:函数式编程reduce 拓展:注意reduce()方法的最后一个参数(下面是个特例),避坑!!! 方法五:forEach遍历

    2024年02月01日
    浏览(44)
  • JS实现深拷贝的几种方法

    这是最简单的方法。 通过递归的方式深度遍历对象,将每个属性的值进行复制。需要处理被复制对象为值类型的情况以及属性值中包含对象的情况。需要注意的是,为了防止循环引用导致死循环,需要记录已经遍历过的对象。 Lodash Lodash 是一个一致性、模块化、高性能的 J

    2024年02月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包