问题 重新渲染Reactjs组件以进行打印


我有一个库组件,它使用当前窗口大小来确定库项目的大小。我还挂钩了窗口调整大小事件,以便在调整窗口大小时正确调整图库项目的大小。

在Chrome中,如果用户随后打印图库,则不会调整项目的大小以适合打印的页面。相反,他们只是使用为窗口大小计算的最后一个大小。即使在打印选项中从纵向切换到横向也是如此。

有什么方法可以在打开打印对话框和页面布局从纵向切换到横向时强制对重新渲染组件做出反应吗?我认为打印对话框会重新呈现具有新尺寸的页面,但似乎并非如此。


4986
2018-01-28 21:26


起源

如果布局对窗口大小调整作出反应,为什么不使用打印CSS来调整窗口大小,从而重新排列布局? - Elad Lachmi
有没有办法告诉纸张尺寸和方向?否则我将不得不硬编码一个不会总是产生正确结果的值。 - Bill


答案:


当您打印页面时,浏览器会获取当前DOM的快照并应用 print 媒体风格。您的问题是DOM上的元素取决于屏幕的尺寸。

窗口调整大小事件将有助于在用户调整屏幕大小时重新排列组件,但在用户打印时不会触发它们。但是,有些方法可以在用户打印页面时收听事件。

window.onbeforeprint 将在用户打印页面时触发。在事件上,您要么调整屏幕大小以使窗口调整大小事件触发器,要么以其他方式重新呈现组件。虽然看看,但Chrome不支持它 这个stackoverflow帖子,它解释了你如何使用 window.matchMedia('print') 代替。

最好依赖于css媒体查询而不是依赖于屏幕尺寸和调整事件大小,但有时这并不总是可行的。


6
2018-02-01 18:35



谢谢你这个Marc,我发现它很有帮助。我在componentWillMount中添加了一个window.matchMedia('print')的监听器,它根据查询是否匹配将状态的'isPrinting'属性更改为true或false,然后调用forceUpdate()。但是,forceUpdate触发的重新渲染仅在打印对话框关闭时发生,此时媒体再次更改。 - Thomas Hopkins
你很受欢迎@ThomasHopkins,很高兴能帮忙。顺便说一句,这是一个很好的解决方案,也许你可以发布其他人的代码,看看它是如何工作的。 - Marc Greenstock
谢谢@MarcGreenstock,但不幸的是,这不是一个解决方案。只有在打印对话框关闭后才会执行forceUpdate上应该重新渲染的重新渲染,到时为止已经太晚了! - Thomas Hopkins


使用媒体查询来定位纵向和横向打印

@media print and (orientation: landscape) {
    /* landscape styles */
    /* write specific styles for landscape e.g */
    h1 {
         color: #000;
         background: none;
      }

      nav, aside {
         display: none;
      }

   }

@media print and (orientation: portrait) {
    /* portrait styles */
}

3
2018-02-02 17:14





除了WitVault的解决方案之外,我还创建了一个简单的React组件,可以更轻松地处理复杂的print.css。您可以使用我的react-print库,而不是在整个标记中添加类,ID等,并创建复杂的print.css文件,如下所示:

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

将此ID添加到当前内容的根目录(或DOM树中的某个位置)(但在body标记内)

<div id="react-no-print"> 

添加id为'print-mount'的div,或者您想要使用的任何mount ID。

<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>
                Your custom HTML or React Components go here, and will replace the existing HTML inside of the "react-no-print" ID, and instead it will render what's inside of your custom template.
            </PrintTemplate>
        );
    }
});

ReactDOM.render(<MyTemplate/>, document.getElementById('print-mount'));

基本上,这会呈现您的可打印版本,但它会被隐藏,直到需要打印。如果您需要这个滑动库,您可能想要挂钩滑块的更改事件并重新渲染(卸载旧的,安装新的)打印模板。

希望这可以帮助!


3
2017-08-14 01:07





你需要使用 matchMedia 组件中的API。但是自己动手,你将重新发明一大堆车轮。使用现有的库来处理这个问题会更容易。请检查 https://www.npmjs.com/package/react-responsive。它有基于React的包装器组件 matchMedia,因此您应该能够在项目中快速对其进行原型设计。还有填充剂。我能想到的另一个优点是,您可以在界面中使用打印预览选项,您可以让用户预览图库在打印模式下的外观。为此,您可以使用此库的服务器呈现功能来模拟打印模式。

PS:我不以任何方式参与这个项目。


1
2018-02-02 12:22