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
接受一个prophead
,您可以使用它传递到样式表的链接。使用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>
);
}
}