1. Download page to generate pdf
1. Install the corresponding dependency package
npm install html2canvas; npm install jspdf --save
2. Create a htmlToPdf.js file in utils and reference it globally in main.js
import html2Canvas from 'html2canvas' import JsPDF from 'jspdf' export default { install(Vue, options) { Vue.prototype.getPdf = function () { var title = this.htmlTitle //DPF title html2Canvas(document. querySelector('#printTest'), { allowTaint: true, taintTest: false, useCORS: true, y:0, // crop the Y axis x:0, // crop the x axis // width:1200, set the width // height:5000, set the height dpi: window.devicePixelRatio * 4, //Increase the resolution to a specific DPI by four times scale: 4 //increase the resolution proportionally }).then(function (canvas) { let contentWidth = canvas. width let contentHeight = canvas.height let pageHeight = contentWidth / 592.28 * 841.89 let leftHeight = contentHeight let position = 0 let imgWidth = 595.28 let imgHeight = 592.28 / contentWidth * contentHeight let pageData = canvas.toDataURL('image/jpeg', 1.0) let PDF = new JsPDF('', 'pt', 'a4') if (leftHeight < pageHeight) { PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) } else { while (leftHeight > 0) { PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) leftHeight -= pageHeight position -= 841.89 if (leftHeight > 0) { PDF. addPage() } } } PDF.save(title + '.pdf') }) } } }
// main.js import htmlToPdf from '@/utils/htmlToPdf' Vue.use(htmlToPdf)
3. Add a label to the vue page, the id is consistent with the js file, declare the variable to specify the pdf name
<div id="printTest">generate pdf content</div>
data() { return { htmlTitle: 'The name of the pdf file to be downloaded' } }
4. Add events
<el-button type="primary" @click="getPdf()">Download</el-button>
2. Print
1. Create a print.js file
//print.js // Print class attributes, method definitions /* eslint-disable */ const Print = function (dom, options) { if (!(this instanceof Print)) return new Print(dom, options); this.options = this.extend({ 'noPrint': '.no-print' }, options); if ((typeof dom) === "string") { this.dom = document.querySelector(dom); } else { this.isDOM(dom) this.dom = this.isDOM(dom) ? dom : dom.$el; } this.init(); }; Print.prototype = { init: function () { var content = this. getStyle() + this. getHtml(); this. writeIframe(content); }, extend: function (obj, obj2) { for (var k in obj2) { obj[k] = obj2[k]; } return obj; }, getStyle: function () { var str = "", styles = document. querySelectorAll('style, link'); for (var i = 0; i < styles. length; i ++ ) { str + = styles[i].outerHTML; } str + = "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>"; // Remove the height: 100% style to solve the problem of style confusion under pagination str + = "<style>html,body,div{height: auto!important;}</style>"; return str; }, getHtml: function () { var inputs = document. querySelectorAll('input'); var textareas = document. querySelectorAll('textarea'); var selects = document. querySelectorAll('select'); var canvas = document. querySelectorAll('canvas'); for (var k = 0; k < inputs. length; k++ ) { if (inputs[k].type == "checkbox" || inputs[k].type == "radio") { if (inputs[k]. checked == true) { inputs[k].setAttribute('checked', "checked") } else { inputs[k].removeAttribute('checked') } } else if (inputs[k].type == "text") { inputs[k].setAttribute('value', inputs[k].value) } else { inputs[k].setAttribute('value', inputs[k].value) } } for (var k2 = 0; k2 < textareas. length; k2++ ) { if (textareas[k2].type == 'textarea') { textareas[k2].innerHTML = textareas[k2].value } } for (var k3 = 0; k3 < selects. length; k3 ++ ) { if (selects[k3].type == 'select-one') { var child = selects[k3].children; for (var i in child) { if (child[i].tagName == 'OPTION') { if (child[i].selected == true) { child[i].setAttribute('selected', "selected") } else { child[i].removeAttribute('selected') } } } } } //canvass echars chart converted to picture for (var k4 = 0; k4 < canvass. length; k4 ++ ) { var imageURL = canvass[k4].toDataURL("image/png"); var img = document.createElement("img"); img.src = imageURL; img.setAttribute('style', 'max-width: 100%;'); img.className = 'isNeedRemove' // canvass[k4].style.display = 'none' // canvass[k4].parentNode.style.width = '100%' // canvass[k4].parentNode.style.textAlign = 'center' canvass[k4].parentNode.insertBefore(img, canvass[k4].nextElementSibling); } // Wrap the element to be printed // fix: https://github.com/xyl66/vuePlugs_printjs/issues/36 // return this.wrapperRefDom(this.dom).outerHTML; return this.dom.outerHTML; }, // Loop to the parent element, wrap the element that needs to be printed currently // Prevent css selectors at the beginning of the root level from not taking effect wrapperRefDom: function (refDom) { let prevDom = null let currDom = refDom while (currDom & amp; & amp; currDom. tagName. toLowerCase() !== 'body') { if (prevDom) { let element = currDom. cloneNode(false) element.appendChild(prevDom) prevDom = element } else { prevDom = currDom. cloneNode(true) } currDom = currDom. parentElement } return currDom.tagName.toLowerCase() === 'body' ? currDom : prevDom }, writeIframe: function (content) { var w, doc, iframe = document.createElement('iframe'), f = document. body. appendChild(iframe); iframe.id = "myIframe"; //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;"; iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;'); w = f.contentWindow || f.contentDocument; doc = f.contentDocument || f.contentWindow.document; doc. open(); doc.write(content); doc. close(); var_this = this iframe.onload = function(){ _this.toPrint(w); setTimeout(function () { document.body.removeChild(iframe) }, 100) } }, toPrint: function (frameWindow) { try { setTimeout(function () { frameWindow. focus(); try { if (!frameWindow.document.execCommand('print', false, null)) { frameWindow. print(); } } catch (e) { frameWindow. print(); } frameWindow. close(); }, 10); } catch (err) { console.log('err', err); } }, isDOM: (typeof HTMLElement === 'object') ? function (obj) { return obj instanceof HTMLElement; } : function (obj) { return obj & amp; & amp; typeof obj === 'object' & amp; & amp; obj.nodeType === 1 & amp; & amp; typeof obj.nodeName === 'string'; } }; const MyPlugin = {} MyPlugin. install = function (Vue, options) { // 4. Add instance method Vue.prototype.$print = Print } export default MyPlugin
You can also install dependencies: npm install vue-print-nb –save
2. Introduce it in main.js and mount it globally
import Print from '@/assets/js/print.js' Vue. use(Print);
3. Add tags
<div id="printTest" ref="print">printed content</div> <el-button type="success" @click="getPrint">Print</el-button>
4. Method
getPrint () { //Add ref to read the label, no-print does not participate in printing, and the printing call is as follows: this. $print(this. $refs. print); //Because each printing will add an img (convert the canvas of echarts to img), the classname added to this img has been configured in my print.js as isNeedRemove, so it needs to be removed after each printing, and I only have one The number of echarts and removal is determined according to business needs. this. $nextTick(() => { let arr = document.getElementsByClassName('isNeedRemove'); if (arr. length) arr[0]. remove(); }); },
5. Modify the style (direct printing style may not be displayed)
@page { size: auto A4 landscape; margin: 20px auto; } @media print { // Write the styles you need here #printTest {} }
If you have better suggestions, please leave your valuable opinions in the comment area! ! !