内容简介:实现逻辑 :弹窗打印实现
实现逻辑 :
- 获取react元素对应的html,
- 构建一个iframe ,把 html 和 css 注入进去,
- 调用iframe 的print api 实现打印效果
printElement.js
import { findDOMNode } from 'react-dom'; import { delay } from 'core-js'; const printElement = options => { const { content, pageStyle, onBeforePrint, onAfterPrint, bodyClass = '', copyStyles = true, } = options; const contentEl = content; if (contentEl === undefined || contentEl === null) { console.error( "Refs are not available for stateless components. For 'react-to-print' to work only Class based components can be printed" ); // eslint-disable-line no-console return; } const printWindow = document.createElement('iframe'); printWindow.style.position = 'absolute'; printWindow.style.top = '-1000px'; printWindow.style.left = '-1000px'; // eslint-disable-next-line const contentNodes = findDOMNode(contentEl); const linkNodes = document.querySelectorAll('link[rel="stylesheet"]'); const linkTotal = linkNodes.length || 0; const linksLoaded = []; const linksErrored = []; const removeWindow = target => { setTimeout(() => { target.parentNode.removeChild(target); }, 500); }; const triggerPrint = target => { if (onBeforePrint) { onBeforePrint(); } setTimeout(() => { target.contentWindow.focus(); target.contentWindow.print(); removeWindow(target); if (onAfterPrint) { onAfterPrint(); } }, 500); }; const markLoaded = (linkNode, loaded) => { if (loaded) { linksLoaded.push(linkNode); } else { console.error( "'react-to-print' was unable to load a link. It may be invalid. 'react-to-print' will continue attempting to print the page. The link the errored was:", linkNode ); // eslint-disable-line no-console linksErrored.push(linkNode); } // We may have errors, but attempt to print anyways - maybe they are trivial and the user will // be ok ignoring them if (linksLoaded.length + linksErrored.length === linkTotal) { triggerPrint(printWindow); } }; printWindow.onload = () => { /* IE11 support */ if (window.navigator && window.navigator.userAgent.indexOf('Trident/7.0') > -1) { printWindow.onload = null; } const domDoc = printWindow.contentDocument || printWindow.contentWindow.document; const srcCanvasEls = [...contentNodes.querySelectorAll('canvas')]; domDoc.open(); domDoc.write(contentNodes.outerHTML); domDoc.close(); /* remove date/time from top */ const defaultPageStyle = pageStyle === undefined ? '@page { size: auto; margin: 0mm; } @media print { body { -webkit-print-color-adjust: exact; } } html,body { overflow: auto!important; height: auto!important; }' : pageStyle; const styleEl = domDoc.createElement('style'); styleEl.appendChild(domDoc.createTextNode(defaultPageStyle)); domDoc.head.appendChild(styleEl); if (bodyClass.length) { domDoc.body.classList.add(bodyClass); } const canvasEls = domDoc.querySelectorAll('canvas'); [...canvasEls].forEach((node, index) => { node.getContext('2d').drawImage(srcCanvasEls[index], 0, 0); }); if (copyStyles !== false) { const headEls = document.querySelectorAll('style, link[rel="stylesheet"]'); [...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++) { // catch 'member not found' error on cssText if (typeof node.sheet.cssRules[i].cssText === 'string') { styleCSS += `${node.sheet.cssRules[i].cssText}\r\n`; } } newHeadEl.setAttribute('id', `react-to-print-${index}`); newHeadEl.appendChild(domDoc.createTextNode(styleCSS)); domDoc.head.appendChild(newHeadEl); } } else { const attributes = [...node.attributes]; const hrefAttr = attributes.filter(attr => attr.nodeName === 'href'); const hasHref = hrefAttr.length ? !!hrefAttr[0].nodeValue : false; // Many browsers will do all sorts of weird things if they encounter an empty `href` // tag (which is invalid HTML). Some will attempt to load the current page. Some will // attempt to load the page's parent directory. These problems can cause // `react-to-print` to stop without any error being thrown. To avoid such problems we // simply do not attempt to load these links. if (hasHref) { const newHeadEl = domDoc.createElement(node.tagName); attributes.forEach(attr => { newHeadEl.setAttribute(attr.nodeName, attr.nodeValue); }); newHeadEl.onload = markLoaded.bind(null, newHeadEl, true); newHeadEl.onerror = markLoaded.bind(null, newHeadEl, false); domDoc.head.appendChild(newHeadEl); } else { console.warn( "'react-to-print' encountered a <link> tag with an empty 'href' attribute. In addition to being invalid HTML, this can cause problems in many browsers, and so the <link> was not loaded. The <link> is:", node ); // eslint-disable-line no-console markLoaded(node, true); // `true` because we've already shown a warning for this } } }); } if (linkTotal === 0 || copyStyles === false) { triggerPrint(printWindow); } }; document.body.appendChild(printWindow); return delay(1000); }; export default printElement; 复制代码
调用打印函数
弹窗打印实现
const PrintTemplage = (props) => { return ( <div> 姓名: {props.name} <br/> 年龄: {props.age} </div> ); } const printData = { name: '小米', age: 32, }; let printDomRef = null; const modal = open({ title: '打印预览', width: 800, maskClosable: false, onOk: () => { printElement({ content: printDomRef, }).then(() => { modal.close(); }); }, style: { minWidth: 400, }, children: ( <div style={{ maxHeight: 640, overflow: 'auto' }}> <PrintTemplage onRef={e => { printDomRef = e; }} {...printData} /> </div> ), }); 复制代码
打印分页实现
如果页面中有某个模块不想被分页时, 被分页切断
可以给需要保留完整的区块添加样式:
.no-cut-area { page-break-inside: avoid; } 复制代码
效果如下
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序员的自我修养
陈逸鹤 / 清华大学出版社 / 2017-5 / 49.00
程序员作为一个职业、也作为一个群体,正逐渐从幕后走向前台,并以他们自己的能力加速改变着世界,也改变着人们生活的方方面面。然而,对于程序员,特别是年轻程序员们来说,如何理解自己的职业与发展,如何看待自己的工作与生活,这些问题往往比那些摆在面前的技术难题更让他们难以解答。 这本书从一个成熟程序员、一名IT管理者的角度,以杂记的形式为大家分享关于国内程序员职业生涯、个人发展、编程中的实践与认知乃至......一起来看看 《程序员的自我修养》 这本书的介绍吧!