关于vue3 局部打印功能遇到的问题,到最后怎么实现的!!!

最近一个业务,要实现局部打印功能,原本我用三个"el-row"标签写了两行内容一个数据表格。首先尝试了, window.print(),可想而知是失败的,直接打印了全部网页,获取局部的代码没有样式。依次尝试了其他插架比如说:print-js、vue3-print-nb都不适用,不是说插件不行,这些插件打印element写出来的页面样式,打印的时候多多少少都是有瑕疵的,要么表格显示不全,要么样式没有,我的解决方案是适用了原生的表格,代码如下。

改成原生表格

       <!-- 打印的内容 -->
      <div id="printContent" style="width: 100%" class="margin-top-15 report-font">
  <table cellspacing="0" border="1" style="width: 100%" class="margin-top-15 table-width-100">
          <tr>
            <td class="center bold" style="width: 5%" v-text="$t('report.number')"></td>
            <td class="center bold" style="width: 29%" v-text="$t('report.name')"></td>
            <td class="center bold" style="width: 18%" v-text="$t('report.lastYearFinalAccounts')"></td>
            <td class="center bold" style="width: 18%" v-text="$t('report.thisYearFinalAccountsDetail')"></td>
            <td class="center bold" style="width: 30%" v-text="$t('report.explain')"></td>
          </tr>
          <template v-if="tableData.length">
            <template v-for="(item, index) in tableData" :key="index">
              <tr class="table-width-100 report-row-height-20">
                <td class="center" style="width: 5%">{{ item.num }}</td>
                <td class="left" style="width: 29%" v-html="stringFormatter(item)"></td>
                <td class="left" style="width: 18%">
                  {{ amountFormatter(item.lastYearFinalAccounts) }}
                </td>
                <td class="left" style="width: 18%">{{amountFormatter(item.currentBudget)}}
                </td>
                <td class="left" style="width: 30%">{{ item.remark }}</td>
              </tr>
            </template>
          </template>
          <template v-else>
            <tr class="table-width-100 report-row-height-20">
              <td colspan="5" style="text-align: center;">
                暂无数据
              </td>
            </tr>
          </template>
        </table>
      </div>

这里有两种打印方案:首先最外层套了一个div设置了一个id为printContent的标签。

  1. 第一种:用iframe打印,页面也不会改变,也不用刷新,也不用重新打开页面。
    首先在template中加入一个隐藏的iframe
  <!--打印用的隐藏的iframe-->
  <iframe width="0" height="0" frameborder="0" id="printIframe"></iframe>

然后就做打印的处理函数

// 处理打印按钮点击事件
const handlePrint = () => {
  //判断表格是否有数据
  if (tableData.value.length === 0) {
    $message.warning(t('general.noData'))
    return
  }
  //因为TypeScript 强制执行更严格的空值检查。所以一些地方加了?或者判断
  //获取打印内容
  const printHtml = document?.getElementById("printContent")?.innerHTML;
  //获取iframe 标签
  const syfPrint = document?.getElementById("printIframe") as HTMLIFrameElement | null;

  if (syfPrint) {
  //获取原页面里的head标签
    const documentHead = document.getElementsByTagName("head")[0];
      //获取iframe 页面里的head标签
    const iframeHead = syfPrint.contentDocument?.getElementsByTagName("head")[0];
	//把原页面的里的head标签内容给到iframe 页面里的head
    if (iframeHead) {
      iframeHead.innerHTML = documentHead.innerHTML;
    }
	//获取iframe 页面里的body,然后把dom结构赋值给iframe 
    const syfPrintBody = syfPrint.contentDocument?.body;
    if (syfPrintBody) {
      syfPrintBody.innerHTML = printHtml || "";
      //执行打印
      syfPrint.contentDocument.execCommand("Print");
    }
  } else {
  //错误提示
    $message.error(t('general.link.error'))
  }
}

这种方式直接在本页面打印,没毛病。
2. 第二中新打开了一个标签页,代码如下:

// 处理打印按钮点击事件
const handlePrint = () => {
  //判断表格是否有数据
  if (tableData.value.length === 0) {
    $message.warning(t('general.noData'))
    return
  }
  //获取本页面样式
    const styles = Array.from(document.styleSheets)
        .map(sheet => Array.from(sheet.cssRules)
            .map(rule => rule.cssText)
            .join('\n'))
        .join('\n');

    // 创建一个新的窗口,以打开打印预览
    const printWindow = window.open('', '_blank');
    printWindow?.document.open();

    // 将当前页面的样式信息添加到新窗口中
    printWindow?.document.write(`
      <html>
        <head>
          <style>
            ${styles}
          </style>
        </head>
        <body>
           ${document?.getElementById("printContent")?.innerHTML}
        </body>
      </html>
    `);

    printWindow?.document.close();
    printWindow?.print();
}

当然,你用原生代码写的,完全可以使用插件,我这里还以我安装的vue3-print-nb为例,直接可以不写打印事件,只要一个打印按钮就行,如下:

  <el-button type="primary" :icon="Printer" v-print="'#printContent'">打印</el-button>

v-print="‘#printContent’"直接指定要打印的标签ID就可以了,其他插架没有尝试,有兴趣可以试试。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现Vue3 + Vite + Electron的打印功能,你可以按照以下步骤进行。 1. 安装Electron 在项目中安装Electron,你可以使用npm命令进行安装: ``` npm install electron --save-dev ``` 2. 创建Electron应用程序 在应用程序的主目录中创建一个名为main.js的文件,并在其中创建一个Electron应用程序: ```javascript const { app, BrowserWindow } = require('electron') function createWindow () { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) win.loadURL('http://localhost:3000') win.webContents.on('did-finish-load', () => { win.webContents.print() }) } app.on('ready', createWindow) ``` 在这个示例中,我们创建了一个Electron窗口,并在窗口加载完成时执行打印操作。 3. 打印Vue3组件 在Vue3组件中,你可以使用window.print()方法来实现打印功能。例如,在一个名为PrintButton.vue的组件中: ```html <template> <button @click="print">打印</button> </template> <script> export default { methods: { print() { window.print() } } } </script> ``` 在这个示例中,我们在组件中创建了一个打印按钮,并在按钮点击时执行打印操作。 4. 运行应用程序 现在,你可以在终端运行Electron应用程序,并访问http://localhost:3000来测试打印功能: ``` electron . ``` 如果一切正常,你应该能够在Electron窗口中看到你的Vue3应用程序,并且能够通过按钮打印内容。 这就是使用Vue3 + Vite + Electron实现打印功能的基本步骤。当然,你还可以根据自己的需求进行更多的定制和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FirstTalent

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值