【问题标题】:react - ensure css loaded before iframe rendersreact - 确保在 iframe 渲染之前加载 css
【发布时间】:2019-12-31 03:53:55
【问题描述】:

处理一闪而过的无样式内容问题。我有一个注入到用户页面的聊天小部件。这样我就不会与现有样式发生冲突。我正在使用react-frame-component 在 iframe 中进行渲染。这很好用,但我遇到的一个问题是 CSS。

react-frame-component 接受一个道具head,您可以使用它来传递指向样式表的链接。使用 MiniCSSExtractPlugin,我可以将我的 css 放入一个单独的文件中,然后我可以链接到:

render(props, state) {
  return (
    <Frame 
      head={<link rel="stylesheet" type="text/css" href="style.css" />}
      scrolling="no"
    >
      <ChatWidget />
    </Frame>
  );
}

有了这个,我得到了无样式内容的可怕闪光。我认为这是因为包括 &lt;ChatWidget&gt; 在内的所有内容都在 css 完全下载之前渲染。

有没有办法确保在所有内容呈现之前下载 CSS?

另外,不确定是否重要,但我正在使用 Preact。

【问题讨论】:

标签: javascript css reactjs webpack preact


【解决方案1】:

我最终编写了自己的 iframe 组件,使用了来自 react-frame-component 的一些技巧,但以一种我可以确定我可以控制它的呈现方式的方式编写它。这是我的 iframe 组件的样子(请注意,它使用 Preact,它与 React 有一些细微差别 - 在 React 中复制它很容易):

import {h, Component, createRef} from 'preact';
import {createPortal} from 'preact/compat';
import {cssLink} from '../utilities';

export default class Frame extends Component {
  iframeNode = createRef();
  iframeTest = document.createElement('iframe');

  static initialContent() {
    return `<!DOCTYPE html><head><link rel="stylesheet" type="text/css" href="${cssLink}"></head><body></body></html>`;
  }

  componentDidMount() {
    this.iframeNode.addEventListener('load', this.handleLoad);
  }

  handleLoad = () => {
    this.iframeRoot = this.iframeNode.contentDocument.body;
    this.forceUpdate();
  };

  sourceProp() {
    const canUseSrcDoc = 'srcdoc' in this.iframeTest;

    if (canUseSrcDoc) {
      return {
        srcdoc: Frame.initialContent(),
      };
    }

    // inserting Frame.initialContent() as the src is a hack for older browsers
    // to allow inserting our stylesheet before the children render, preventing
    // flashes of unstyled content
    return {
      src: `javascript: '${Frame.initialContent()}'`,
    };
  }

  render(props) {
    const {children, ...rest} = props;

    return (
      <iframe
        {...rest}
        {...this.sourceProp()}
        ref={ref => (this.iframeNode = ref)}
      >
        {this.iframeRoot && createPortal(children, this.iframeRoot)}
      </iframe>
    );
  }
}

【讨论】:

    猜你喜欢
    • 2019-01-19
    • 2018-07-26
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    相关资源
    最近更新 更多