如何在单击按钮时打印 React 组件?
How to print React component on click of a button?
如何在单击一个按钮时只打印一个组件。
我知道这个解决方案:
window.frames["print_frame"].window.focus();
window.frames["print_frame"].window.print();
$('.print_frame').remove();
但是 React 不想使用框架。
有什么解决办法吗?谢谢。
客户端有两种解决方案。一个是像你发布的框架。不过,您可以使用 iframe:
var content = document.getElementById("divcontents");
var pri = document.getElementById("ifmcontentstoprint").contentWindow;
pri.document.open();
pri.document.write(content.innerHTML);
pri.document.close();
pri.focus();
pri.print();
这预计 html 存在
<iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe>
另一个解决方案是使用媒体选择器并在 media="print"
样式上隐藏您不想打印的所有内容。
<style type="text/css" media="print">
.no-print { display: none; }
</style>
最后一种方法需要在服务器上做一些工作。您可以将所有 HTML+CSS 发送到服务器并使用众多组件之一生成可打印文档,如 PDF。我已经尝试使用 PhantomJs 进行设置。
您必须在 CSS 中使用 @media print {}
设置打印输出的样式,但简单的代码是:
export default class Component extends Component {
print(){
window.print();
}
render() {
...
<span className="print"
onClick={this.print}>
PRINT
</span>
}
}
希望对您有所帮助!
如果您要打印您已经有权访问的特定数据,无论是来自商店、AJAX 还是其他地方可用,您都可以利用我的库 react-print。
https://github.com/captray/react-print
它使创建打印模板变得更加容易(假设您已经依赖于 React)。您只需要适当地标记您的 HTML 即可。
此 ID 应添加到您实际的 DOM 树中更高的位置,以排除除下方 "print mount" 之外的所有内容。
<div id="react-no-print">
这是你的 react-print 组件将挂载和包装你创建的模板的地方:
<div id="print-mount"></div>
示例如下所示:
var PrintTemplate = require('react-print');
var ReactDOM = require('react-dom');
var React = require('react');
var MyTemplate = React.createClass({
render() {
return (
<PrintTemplate>
<p>Your custom</p>
<span>print stuff goes</span>
<h1>Here</h1>
</PrintTemplate>
);
}
});
ReactDOM.render(<MyTemplate/>, document.getElementById('print-mount'));
值得注意的是,您可以在模板中创建新的或利用现有的子组件,并且所有内容都应该可以正常打印。
2017 年 6 月 19 日这对我来说很完美。
import React, { Component } from 'react'
class PrintThisComponent extends Component {
render() {
return (
<div>
<button onClick={() => window.print()}>PRINT</button>
<p>Click above button opens print preview with these words on page</p>
</div>
)
}
}
export default PrintThisComponent
我一直在寻找一个简单的包来完成同样的任务,但没有找到任何东西,所以我创建了 https://github.com/gregnb/react-to-print
你可以这样使用它:
<ReactToPrint
trigger={() => <a href="#">Print this out!</a>}
content={() => this.componentRef}
/>
<ComponentToPrint ref={el => (this.componentRef = el)} />
只是分享在我的案例中有用的东西,因为其他人可能会发现它有用。我有一个模态,只是想打印模态的主体,它可能是纸上的几页。
我尝试过的其他解决方案只打印了一页,而且只打印了屏幕上显示的内容。 Emil 接受的解决方案对我有用:
这就是组件最终的样子。它打印模态主体中的所有内容。
import React, { Component } from 'react';
import {
Button,
Modal,
ModalBody,
ModalHeader
} from 'reactstrap';
export default class TestPrint extends Component{
constructor(props) {
super(props);
this.state = {
modal: false,
data: [
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test'
]
}
this.toggle = this.toggle.bind(this);
this.print = this.print.bind(this);
}
print() {
var content = document.getElementById('printarea');
var pri = document.getElementById('ifmcontentstoprint').contentWindow;
pri.document.open();
pri.document.write(content.innerHTML);
pri.document.close();
pri.focus();
pri.print();
}
renderContent() {
var i = 0;
return this.state.data.map((d) => {
return (<p key={d + i++}>{i} - {d}</p>)
});
}
toggle() {
this.setState({
modal: !this.state.modal
})
}
render() {
return (
<div>
<Button
style={
{
'position': 'fixed',
'top': '50%',
'left': '50%',
'transform': 'translate(-50%, -50%)'
}
}
onClick={this.toggle}
>
Test Modal and Print
</Button>
<Modal
size='lg'
isOpen={this.state.modal}
toggle={this.toggle}
className='results-modal'
>
<ModalHeader toggle={this.toggle}>
Test Printing
</ModalHeader>
<iframe id="ifmcontentstoprint" style={{
height: '0px',
width: '0px',
position: 'absolute'
}}></iframe>
<Button onClick={this.print}>Print</Button>
<ModalBody id='printarea'>
{this.renderContent()}
</ModalBody>
</Modal>
</div>
)
}
}
注意:但是,我很难在 iframe
中反映样式。
首先要感谢@emil-ingerslev 的精彩回答。我对其进行了测试,并且效果很好。但是有两件事我想改进。
- 我不喜欢 dom 树中已经有
<iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe>
。
- 我想创建一种方法使其可重复使用。
我希望这能让其他人开心并节省几分钟的生命。现在去花额外的时间为某人做点好事。
function printPartOfPage(elementId, uniqueIframeId){
const content = document.getElementById(elementId)
let pri
if (document.getElementById(uniqueIframeId)) {
pri = document.getElementById(uniqueIframeId).contentWindow
} else {
const iframe = document.createElement('iframe')
iframe.setAttribute('title', uniqueIframeId)
iframe.setAttribute('id', uniqueIframeId)
iframe.setAttribute('style', 'height: 0px; width: 0px; position: absolute;')
document.body.appendChild(iframe)
pri = iframe.contentWindow
}
pri.document.open()
pri.document.write(content.innerHTML)
pri.document.close()
pri.focus()
pri.print()
}
编辑 2019-7-23:在更多地使用它之后,它确实有一个缺点,即它不能完美地渲染反应组件。当样式是内联的时,这对我有用,但当由样式化组件或其他一些情况处理时,这对我不起作用。如果我想出万无一失的方法,我会更新。
Emil Ingerslev 提供的解决方案运行良好,但 CSS 未应用于输出。在这里我找到了Andrewlimaza给出的一个很好的解决方案。它打印给定 div 的内容,因为它使用 window 对象的打印方法,所以 CSS 不会丢失。而且也不需要额外的 iframe。
var printContents = document.getElementById("divcontents").innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
更新 1:
在 chrome/firefox/opera/edge 中存在异常行为,执行此代码后打印或其他按钮停止工作。
更新 2:
给出的解决方案在上面link的评论中:
.printme { display: none;}
@media print {
.no-printme { display: none;}
.printme { display: block;}
}
<h1 class = "no-printme"> do not print this </h1>
<div class='printme'>
Print this only
</div>
<button onclick={window.print()}>Print only the above div</button>
完美解决方案:
class PrintThisComponent extends Component {
render() {
return (
<div>
<button className="btn btn-success btn-lg"
onClick={() => window.print()}>
PRINT
</button>
</div>
)
}
}
export default PrintThisComponent;
只需转到 React 文件中的任何位置并执行以下操作:
import PrintThisComponent from 'the file having above code';
<PrintThisComponent />
如何在单击一个按钮时只打印一个组件。
我知道这个解决方案:
window.frames["print_frame"].window.focus();
window.frames["print_frame"].window.print();
$('.print_frame').remove();
但是 React 不想使用框架。
有什么解决办法吗?谢谢。
客户端有两种解决方案。一个是像你发布的框架。不过,您可以使用 iframe:
var content = document.getElementById("divcontents");
var pri = document.getElementById("ifmcontentstoprint").contentWindow;
pri.document.open();
pri.document.write(content.innerHTML);
pri.document.close();
pri.focus();
pri.print();
这预计 html 存在
<iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe>
另一个解决方案是使用媒体选择器并在 media="print"
样式上隐藏您不想打印的所有内容。
<style type="text/css" media="print">
.no-print { display: none; }
</style>
最后一种方法需要在服务器上做一些工作。您可以将所有 HTML+CSS 发送到服务器并使用众多组件之一生成可打印文档,如 PDF。我已经尝试使用 PhantomJs 进行设置。
您必须在 CSS 中使用 @media print {}
设置打印输出的样式,但简单的代码是:
export default class Component extends Component {
print(){
window.print();
}
render() {
...
<span className="print"
onClick={this.print}>
PRINT
</span>
}
}
希望对您有所帮助!
如果您要打印您已经有权访问的特定数据,无论是来自商店、AJAX 还是其他地方可用,您都可以利用我的库 react-print。
https://github.com/captray/react-print
它使创建打印模板变得更加容易(假设您已经依赖于 React)。您只需要适当地标记您的 HTML 即可。
此 ID 应添加到您实际的 DOM 树中更高的位置,以排除除下方 "print mount" 之外的所有内容。
<div id="react-no-print">
这是你的 react-print 组件将挂载和包装你创建的模板的地方:
<div id="print-mount"></div>
示例如下所示:
var PrintTemplate = require('react-print');
var ReactDOM = require('react-dom');
var React = require('react');
var MyTemplate = React.createClass({
render() {
return (
<PrintTemplate>
<p>Your custom</p>
<span>print stuff goes</span>
<h1>Here</h1>
</PrintTemplate>
);
}
});
ReactDOM.render(<MyTemplate/>, document.getElementById('print-mount'));
值得注意的是,您可以在模板中创建新的或利用现有的子组件,并且所有内容都应该可以正常打印。
2017 年 6 月 19 日这对我来说很完美。
import React, { Component } from 'react'
class PrintThisComponent extends Component {
render() {
return (
<div>
<button onClick={() => window.print()}>PRINT</button>
<p>Click above button opens print preview with these words on page</p>
</div>
)
}
}
export default PrintThisComponent
我一直在寻找一个简单的包来完成同样的任务,但没有找到任何东西,所以我创建了 https://github.com/gregnb/react-to-print
你可以这样使用它:
<ReactToPrint
trigger={() => <a href="#">Print this out!</a>}
content={() => this.componentRef}
/>
<ComponentToPrint ref={el => (this.componentRef = el)} />
只是分享在我的案例中有用的东西,因为其他人可能会发现它有用。我有一个模态,只是想打印模态的主体,它可能是纸上的几页。
我尝试过的其他解决方案只打印了一页,而且只打印了屏幕上显示的内容。 Emil 接受的解决方案对我有用:
这就是组件最终的样子。它打印模态主体中的所有内容。
import React, { Component } from 'react';
import {
Button,
Modal,
ModalBody,
ModalHeader
} from 'reactstrap';
export default class TestPrint extends Component{
constructor(props) {
super(props);
this.state = {
modal: false,
data: [
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test',
'test', 'test', 'test', 'test', 'test', 'test'
]
}
this.toggle = this.toggle.bind(this);
this.print = this.print.bind(this);
}
print() {
var content = document.getElementById('printarea');
var pri = document.getElementById('ifmcontentstoprint').contentWindow;
pri.document.open();
pri.document.write(content.innerHTML);
pri.document.close();
pri.focus();
pri.print();
}
renderContent() {
var i = 0;
return this.state.data.map((d) => {
return (<p key={d + i++}>{i} - {d}</p>)
});
}
toggle() {
this.setState({
modal: !this.state.modal
})
}
render() {
return (
<div>
<Button
style={
{
'position': 'fixed',
'top': '50%',
'left': '50%',
'transform': 'translate(-50%, -50%)'
}
}
onClick={this.toggle}
>
Test Modal and Print
</Button>
<Modal
size='lg'
isOpen={this.state.modal}
toggle={this.toggle}
className='results-modal'
>
<ModalHeader toggle={this.toggle}>
Test Printing
</ModalHeader>
<iframe id="ifmcontentstoprint" style={{
height: '0px',
width: '0px',
position: 'absolute'
}}></iframe>
<Button onClick={this.print}>Print</Button>
<ModalBody id='printarea'>
{this.renderContent()}
</ModalBody>
</Modal>
</div>
)
}
}
注意:但是,我很难在 iframe
中反映样式。
首先要感谢@emil-ingerslev 的精彩回答。我对其进行了测试,并且效果很好。但是有两件事我想改进。
- 我不喜欢 dom 树中已经有
<iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe>
。 - 我想创建一种方法使其可重复使用。
我希望这能让其他人开心并节省几分钟的生命。现在去花额外的时间为某人做点好事。
function printPartOfPage(elementId, uniqueIframeId){
const content = document.getElementById(elementId)
let pri
if (document.getElementById(uniqueIframeId)) {
pri = document.getElementById(uniqueIframeId).contentWindow
} else {
const iframe = document.createElement('iframe')
iframe.setAttribute('title', uniqueIframeId)
iframe.setAttribute('id', uniqueIframeId)
iframe.setAttribute('style', 'height: 0px; width: 0px; position: absolute;')
document.body.appendChild(iframe)
pri = iframe.contentWindow
}
pri.document.open()
pri.document.write(content.innerHTML)
pri.document.close()
pri.focus()
pri.print()
}
编辑 2019-7-23:在更多地使用它之后,它确实有一个缺点,即它不能完美地渲染反应组件。当样式是内联的时,这对我有用,但当由样式化组件或其他一些情况处理时,这对我不起作用。如果我想出万无一失的方法,我会更新。
Emil Ingerslev 提供的解决方案运行良好,但 CSS 未应用于输出。在这里我找到了Andrewlimaza给出的一个很好的解决方案。它打印给定 div 的内容,因为它使用 window 对象的打印方法,所以 CSS 不会丢失。而且也不需要额外的 iframe。
var printContents = document.getElementById("divcontents").innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
更新 1: 在 chrome/firefox/opera/edge 中存在异常行为,执行此代码后打印或其他按钮停止工作。
更新 2: 给出的解决方案在上面link的评论中:
.printme { display: none;}
@media print {
.no-printme { display: none;}
.printme { display: block;}
}
<h1 class = "no-printme"> do not print this </h1>
<div class='printme'>
Print this only
</div>
<button onclick={window.print()}>Print only the above div</button>
完美解决方案:
class PrintThisComponent extends Component {
render() {
return (
<div>
<button className="btn btn-success btn-lg"
onClick={() => window.print()}>
PRINT
</button>
</div>
)
}
}
export default PrintThisComponent;
只需转到 React 文件中的任何位置并执行以下操作:
import PrintThisComponent from 'the file having above code';
<PrintThisComponent />