【问题标题】:Re-render Reactjs components for print重新渲染 Reactjs 组件以进行打印
【发布时间】:2016-05-06 11:17:24
【问题描述】:

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

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

当打印对话框打开并且页面布局从纵向切换到横向时,是否有任何方法可以强制对重新渲染组件做出反应?我认为打印对话框会使用新尺寸重新渲染页面,但事实并非如此。

【问题讨论】:

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

标签: printing reactjs


【解决方案1】:

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

当用户调整屏幕大小时,窗口调整大小事件将有助于重新排列组件,但在用户打印时不会触发它们。但是,您可以通过多种方式在用户打印页面时监听事件。

window.onbeforeprint 将在用户打印页面时触发。在事件中,您要么调整屏幕大小以触发窗口调整大小事件,要么以其他方式重新渲染组件。 chrome 不支持它,尽管看看this stackoverflow post,它解释了如何使用window.matchMedia('print')

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

【讨论】:

  • 感谢 Marc,我发现它很有帮助。我在componentWillMount 中为window.matchMedia('print') 添加了一个监听器,它根据查询是否匹配将状态上的'isPrinting' 属性更改为true 或false,然后调用forceUpdate()。但是,由 forceUpdate 触发的重新渲染仅在打印对话框关闭后才会发生,此时媒体会再次更改。
  • 不客气@ThomasHopkins,很高兴我能帮上忙。顺便说一句,这是一个不错的解决方案,也许您可​​以将代码发布给其他人看看它是如何工作的。
  • 感谢@MarcGreenstock,但不幸的是这不是解决方案。应该在 forceUpdate 上发生的重新渲染仅在打印对话框关闭后执行,到那时为时已晚!
  • window.onbeforeprint 现在受 Chrome (63+) 支持。 developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/…
【解决方案2】:

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

@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】:

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

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

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

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

    添加一个 id 为“print-mount”的 div,或者您想使用的任何安装 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'));
    

    基本上,这会呈现您的可打印版本,但在需要打印之前它是隐藏的。如果您需要将它用于滑动画廊,您可能希望挂钩到滑块的更改事件并重新渲染(卸载旧的,安装新的)打印模板。

    希望这会有所帮助!

    【讨论】:

      【解决方案4】:

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

      PS:我与这个项目没有任何关系。

      【讨论】:

        猜你喜欢
        • 2023-04-11
        • 2020-06-20
        • 2019-01-01
        • 2012-01-05
        • 2018-09-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-25
        • 2021-12-06
        相关资源
        最近更新 更多