【问题标题】:How to print a specific element in Vue 3?如何在 Vue 3 中打印特定元素?
【发布时间】:2021-02-25 15:41:20
【问题描述】:

我正在开展一个项目,我希望该功能能够打印我的页面的特定元素。有一个名为 VueHtmlToPaper 的 mixin/plugin 可以完全满足我的需求,但是我无法将它导入到我的 Vue 3 CLI 项目中,因为它是为 VueJS2 创建的并且全局 API 不同。任何帮助表示赞赏。

ma​​in.js

import { createApp } from 'vue'

import App from './App.vue'

 createApp(App).mount('#app')

项目结构:

【问题讨论】:

  • 请分享你是如何使用 vue 2 的
  • 我以前没用过,但这是插件link 的文档,在 vue 3 中,您使用 createApp 创建 vue 实例,因此您无权访问 Vue.use
  • 这个插件与vue 3不兼容,你应该寻找另一个插件或等他们发布与vue 3兼容的新版本
  • 但我认为我能够根据他们的代码提供适用于 vue 3 的代码,请给我一些时间尝试一下
  • 非常感谢!那真的会帮助我。我很确定所有代码都在 src/index.js 中。我对 vanilla javascript 非常不擅长,所以我无法理解该代码。

标签: javascript vue.js printing vuejs3 vue-cli-4


【解决方案1】:

由于这个插件与vue 3不兼容,我们可以基于vue-html-to-paper插件来做我们的插件:

  1. 在项目根目录中创建一个名为 plugins 的文件夹,然后在其中添加具有以下内容的 VueHtmlToPaper.js 文件:

function addStyles(win, styles) {
    styles.forEach((style) => {
      let link = win.document.createElement("link");
      link.setAttribute("rel", "stylesheet");
      link.setAttribute("type", "text/css");
      link.setAttribute("href", style);
      win.document.getElementsByTagName("head")[0].appendChild(link);
    });
  }
  
  const VueHtmlToPaper = {
    install(app, options = {}) {
      app.config.globalProperties.$htmlToPaper = (
        el,
        localOptions,
        cb = () => true
      ) => {
        let defaultName = "_blank",
          defaultSpecs = ["fullscreen=yes", "titlebar=yes", "scrollbars=yes"],
          defaultReplace = true,
          defaultStyles = [];
        let {
          name = defaultName,
          specs = defaultSpecs,
          replace = defaultReplace,
          styles = defaultStyles
        } = options;
  
        // If has localOptions
        // TODO: improve logic
        if (!!localOptions) {
          if (localOptions.name) name = localOptions.name;
          if (localOptions.specs) specs = localOptions.specs;
          if (localOptions.replace) replace = localOptions.replace;
          if (localOptions.styles) styles = localOptions.styles;
        }
  
        specs = !!specs.length ? specs.join(",") : "";
  
        const element = window.document.getElementById(el);
  
        if (!element) {
          alert(`Element to print #${el} not found!`);
          return;
        }
  
        const url = "";
        const win = window.open(url, name, specs, replace);
  
        win.document.write(`
          <html>
            <head>
              <title>${window.document.title}</title>
            </head>
            <body>
              ${element.innerHTML}
            </body>
          </html>
        `);
  
        addStyles(win, styles);
  
        setTimeout(() => {
          win.document.close();
          win.focus();
          win.print();
          win.close();
          cb();
        }, 1000);
  
        return true;
      };
    }
  };
  
  export default VueHtmlToPaper;
  

我刚刚复制/粘贴了这个code,并将Vue 替换为app,然后将其导入main.js

import { createApp } from 'vue'

import App from './App.vue'

 import  VueHtmlToPaper from './plugins/VueHtmlToPaper'

let app=createApp(App);

 app.use(VueHtmlToPaper)

 app.mount('#app')

然后在任何组件中使用它:

<template>
<div class="home">
    <img alt="Vue logo" src="../assets/logo.png">

    <!-- SOURCE -->
    <div id="printMe">
        <h1>Print me!</h1>
    </div>
    <!-- OUTPUT -->
    <button @click="print">print</button>

</div>
</template>

<script lang="ts">
import {
    defineComponent
} from 'vue';
import HelloWorld from '@/components/HelloWorld.vue'; /

export default defineComponent({
    name: 'Home',
    components: {
        HelloWorld,
    },
    methods: {
        print() {
            this.$htmlToPaper('printMe')
        }
    },
    mounted() {

    }
});
</script>

LIVE DEMO

【讨论】:

  • 它似乎有效。我必须删除双重否定!不过在 VueHtmlToPaper.js 中。谢谢。
  • 您是否设法在选项中使用了本地 css 文件?我无法以某种方式完成它。
  • 你的意思是在head元素下面吗?
【解决方案2】:

您是否设法在选项中使用了本地 css 文件?我无法以某种方式完成它。组件中的某些内容,例如

methods: {
  print: function() {
  
    const printOptions = {
      name: '_blank',
      specs: [
        'fullscreen=yes',
        'titlebar=yes',
        'scrollbars=yes'
      ],
      styles: [
        'path/to/my/local/bulma.css',
        'path/to/some/custom/print.css'
        //I tried the correct path from the component to the css as well as something like '@/assets/print.css'
      ]
    }

    this.$htmlToPaper('app', printOptions, () => {
      console.log('Printing finished');
      // whatever
    });
  }
}

【讨论】:

  • 你有没有回答过这个问题,如何将本地 CSS 文件添加到打印输出中?
  • 如果我没记错的话,我从来没有让它正常工作。我的最终解决方案是使用 pdfkit.org/ 构建一个 pdf,这对我来说效果更好。
【解决方案3】:

为了防止出现额外的窗口,我用 VueHtmlToPaper.js 中的 iframe 替换了 window

function addStyles(win, styles) {
    styles.forEach((style) => {
      let link = win.document.createElement("link");
      link.setAttribute("rel", "stylesheet");
      link.setAttribute("type", "text/css");
      link.setAttribute("href", style);
      win.document.getElementsByTagName("head")[0].appendChild(link);
    });
  }
  
  const VueHtmlToPaper = {
    install(app, options = {}) {
      app.config.globalProperties.$htmlToPaper = (
        el,
        localOptions,
        cb = () => true
      ) => {
        let 
          defaultStyles = [];
        let {
          styles = defaultStyles
        } = options;
  
        // If has localOptions
        // TODO: improve logic
        if (localOptions) {
          if (localOptions.styles) styles = localOptions.styles;
        }
  
        const element = window.document.getElementById(el);
  
        if (!element) {
          alert(`Element to print #${el} not found!`);
          return;
        }
  
        var ifprint = document.createElement("iframe");
        document.body.appendChild(ifprint);
        ifprint.setAttribute("style","height:0;width:0;");

        const win = ifprint.contentWindow;
  
        win.document.write(`
          <html>
            <head>
              <title>${window.document.title}</title>
            </head>
            <body>
              ${element.innerHTML}
            </body>
          </html>
        `);
  
        addStyles(win, styles);
        
  
        setTimeout(() => {
          win.document.close();
          win.focus();
          win.print();
          win.close();
          document.body.removeChild(ifprint);
          cb();
        }, 1);
  
        return true;
      };
    }
  };
  
  export default VueHtmlToPaper;

【讨论】:

  • 感谢您发布此内容,不确定您指的是哪个额外的窗口,但在我用您的代码替换原始代码之前,我无法让 Microsoft Print to PDF 显示保存文件对话框。跨度>
猜你喜欢
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-26
  • 2012-02-07
相关资源
最近更新 更多