Javascript 反应-确保在iframe渲染之前加载css

Javascript 反应-确保在iframe渲染之前加载css,javascript,css,reactjs,webpack,preact,Javascript,Css,Reactjs,Webpack,Preact,处理未设置样式的内容问题。我有一个聊天小部件,它被注入用户的页面。这样我就不会与现有的样式冲突。我正在使用react frame component在iframe中进行渲染。这非常好用,但我有一个问题是CSS react frame component接受一个prophead,您可以使用它传递到样式表的链接。使用MiniCSSExtractPlugin,我可以将我的css放入一个单独的文件中,然后链接到: render(props, state) { return ( <Fra

处理未设置样式的内容问题。我有一个聊天小部件,它被注入用户的页面。这样我就不会与现有的样式冲突。我正在使用
react frame component
在iframe中进行渲染。这非常好用,但我有一个问题是CSS

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

render(props, state) {
  return (
    <Frame 
      head={<link rel="stylesheet" type="text/css" href="style.css" />}
      scrolling="no"
    >
      <ChatWidget />
    </Frame>
  );
}
渲染(道具、状态){
返回(
);
}
有了这个,我得到了可怕的未格式化内容的闪光。我认为这是因为包括
在内的所有内容都是在css完全下载之前呈现的

有没有一种方法可以确保在呈现所有内容之前下载CSS


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

我最终编写了自己的iframe组件,使用了
react frame component
中的一些技巧,但以一种我可以确保能够控制其渲染方式的方式编写。以下是我的iframe组件的外观(注意,这使用了Preact,它与React有一些细微的区别-在React中复制它非常容易):

从'preact'导入{h,Component,createRef};
从'preact/compat'导入{createPortal};
从“../utilities”导入{cssLink};
导出默认类框架扩展组件{
iframeNode=createRef();
iframeTest=document.createElement('iframe');
静态初始化内容(){
返回``;
}
componentDidMount(){
this.iframeNode.addEventListener('load',this.handleLoad);
}
手动加载=()=>{
this.iframeRoot=this.iframeNode.contentDocument.body;
这个.forceUpdate();
};
sourceProp(){
const canusescrcdoc='srcdoc'在this.iframeTest中;
如果(canUseSrcDoc){
返回{
srcdoc:Frame.initialContent(),
};
}
//将Frame.initialContent()作为src插入是对旧浏览器的一种攻击
//允许在子级渲染之前插入样式表,以防止
//未格式化内容的闪烁
返回{
src:`javascript:'${Frame.initialContent()}`,
};
}
渲染(道具){
const{children,…rest}=props;
返回(
(this.iframeNode=ref)}
>
{this.iframeRoot&&createPortal(子项,this.iframeRoot)}
);
}
}

为了速度,我不会那样做。尝试使用主文档中的CSS预加载,或者将所需的CSS内联到框架组件中。你解决了吗?是的,刚刚发布了一个答案
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>
    );
  }
}