如何在单击按钮时打印React组件?

时间:2015-05-09 02:45:02

标签: javascript reactjs

如何在单击按钮时仅打印一个组件。

我知道这个解决方案:

window.frames["print_frame"].window.focus();
window.frames["print_frame"].window.print();
$('.print_frame').remove();

但是React不想使用框架。

任何解决方案?谢谢。

9 个答案:

答案 0 :(得分:22)

客户端有两种解决方案。一个是你发布的帧。您可以使用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进行设置。

答案 1 :(得分:9)

2017年6月19日这对我来说非常适合。

import React, {Component} from 'react'


class PrintThisComponent extends Component {

  componentDidMount() {

    console.log('PrintThisComponent mounted!')

  }

  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

答案 2 :(得分:5)

如果您要打印已经访问过的特定数据,无论是来自Store,AJAX还是其他地方,您都可以利用我的库react-print。

https://github.com/captray/react-print

这使得创建打印模板变得更加容易(假设您已经依赖于react)。您只需要适当地标记HTML。

此ID应添加到实际DOM树的较高位置,以排除除下面“打印装载”之外的所有内容。

<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'));

值得注意的是,您可以在模板中创建新的或利用现有的子组件,并且所有内容都应该可以正常打印。

答案 3 :(得分:3)

您必须在CSS中使用@media print {}设置打印输出样式,但简单的代码是:

export default class Component extends Component {

    print(){
        window.print();
    }


  render() {

  ...
  <span className="print"
              onClick={this.print}>
    PRINT
    </span>

  } 
}

希望有帮助!

答案 4 :(得分:3)

我一直在寻找一个简单的程序包,它可以完成同样的任务而且找不到任何东西,所以我创建了https://github.com/gregnb/react-to-print

您可以像这样使用它:

 <ReactToPrint
   trigger={() => <a href="#">Print this out!</a>}
   content={() => this.componentRef}
 />
 <ComponentToPrint ref={el => (this.componentRef = el)} />

答案 5 :(得分:2)

Emil Ingerslev提供的解决方案工作正常,但是CSS不适用于输出。在这里,我找到了Andrewlimaza给出的很好的解决方案。它使用窗口对象的打印方法打印给定div的内容,因此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>

答案 6 :(得分:0)

只是像其他人一样分享在我的案例中有用的东西可能会发现它很有用。我有一个模态,只是想打印模态的主体,可能是纸上的几页。

我试过的其他解决方案只打印了一页,而且只打印在屏幕上。 Emil的公认解决方案对我有用:

https://stackoverflow.com/a/30137174/3123109

这就是组件最终看起来的样子。它会打印出模态体内的所有内容。

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

答案 7 :(得分:0)

首先要感谢@ emil-ingerslev一个很棒的答案。我对其进行了测试,并且效果很好。但是有两件事我想改进。

  1. 我不喜欢在dom树中已经有了<iframe id="ifmcontentstoprint" style="height: 0px; width: 0px; position: absolute"></iframe>
  2. 我想创造一种使它可重用的方法。

我希望这可以使其他人感到高兴并节省几分钟的生命。现在,多花些时间为别人做点好事。

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()
}

答案 8 :(得分:-1)

完美解决方案:

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 />