說到打印前端頁(yè)面中的內(nèi)容诵原,第一時(shí)間想到的方法就是window.print(),但是這個(gè)方法其實(shí)是會(huì)把當(dāng)前頁(yè)面上全部的內(nèi)容(body標(biāo)簽內(nèi)所包裹的)全部打印出來(lái),顯然是不符合我們的需求的,所以稍作變通篮绰,獲取需要打印的部分的內(nèi)容,賦值到body標(biāo)簽中季惯,方式如下:
const print = () => {
window.document.body.innerHTML = window.document.getElementById('content').innerHTML;
window.print();
window.location.reload();
}
這樣做確實(shí)可以實(shí)現(xiàn)打印局部?jī)?nèi)容的功能吠各,但是有一個(gè)問題,由于我們把當(dāng)前頁(yè)面的內(nèi)容賦值給了要打印的內(nèi)容星瘾,打印完成之后是需要重新加載這一頁(yè)面的(即使打印操作完成后將頁(yè)面內(nèi)容賦值回原來(lái)的也不行,因?yàn)闊o(wú)法判斷用戶點(diǎn)的是打印還是取消按鈕)惧辈。
為了達(dá)到更好的效果琳状,在網(wǎng)上搜索相關(guān)資料,找到了一個(gè)組件react-to-print
npm install --save react-to-print
使用方法有很多種盒齿,我們就選擇調(diào)用useReactToPrint這一種:
const handlePrint = useReactToPrint({
content: () => componentRef.current,
});
只需要將對(duì)應(yīng)的需要打印的內(nèi)容的ref傳入即可念逞,當(dāng)然還可以傳入其他的參數(shù),可以在其GitHub頁(yè)面中查看边翁。
其實(shí)這個(gè)react-to-print也是借助于iframe來(lái)實(shí)現(xiàn)局部打印的功能的翎承,我們可以試著來(lái)實(shí)現(xiàn)最基本的功能:
import { findDOMNode } from 'react-dom';
// content即為要打印的內(nèi)容
const Print = (content) => {
if (content === undefined || content === null) {
return;
}
// 創(chuàng)建一個(gè)iframe
const printWindow = document.createElement('iframe');
printWindow.style.position = 'absolute';
printWindow.style.top = '-1000px';
printWindow.style.left = '-1000px';
const contentNodes = findDOMNode(content);
// 打印完成后關(guān)閉iframe窗口
const removeWindow = (target) => {
setTimeout(() => {
target.parentNode.removeChild(target);
}, 500);
};
// 觸發(fā)打印操作
const triggerPrint = (target) => {
setTimeout(() => {
target.contentWindow.focus();
target.contentWindow.print();
removeWindow(target);
}, 500);
};
printWindow.onload = () => {
const domDoc = printWindow.contentDocument || printWindow.contentWindow.document;
domDoc.open();
domDoc.write(contentNodes.outerHTML);
domDoc.close();
const defaultPageStyle = `
@page {
size: auto;
margin: 0mm;
}
@media print {
body {
-webkit-print-color-adjust: exact;
}
}
html,body {
overflow: auto!important;
height: auto!important;
}`;
const styleEl =domDoc.createElement('style');
styleEl.appendChild(domDoc.createTextNode(defaultPageStyle));
domDoc.head.appendChild(styleEl);
// 復(fù)制原先的樣式
const headEls = document.querySelectorAll('style, link[rel="stylesheet"]');
Array.from(headEls).forEach((node, index) => {
if (node.tagName === 'STYLE') {
const newHeadEl = domDoc.createElement(node.tagName);
if (node.sheet) {
let styleCSS = '';
for (let i = 0; i < node.sheet.cssRules.length; i++) {
if (typeof node.sheet.cssRules[i].cssText === 'string') {
styleCSS += ''.concat(node.sheet.cssRules[i].cssText, '\r\n');
}
}
newHeadEl.setAttribute('id', 'react-to-print-'.concat(index));
newHeadEl.appendChild(domDoc.createTextNode(styleCSS));
domDoc.head.appendChild(newHeadEl);
}
}
});
triggerPrint(printWindow);
};
document.body.appendChild(printWindow);
};
export default Print;