反应 - 确保 css 在 iframe 呈现之前加载
react - ensure css loaded before iframe renders
正在处理一闪而过的无样式内容问题。我有一个注入到用户页面的聊天小部件。这样我就不会与现有样式发生冲突。我正在使用 react-frame-component
在 iframe 中呈现。这工作得很好,但我遇到的一个问题是 CSS.
react-frame-component
接受一个道具 head
,您可以使用它来将 link 传递给样式表。使用 MiniCSSExtractPlugin,我能够将我的 css 放入一个单独的文件中,然后我可以 link 到:
render(props, state) {
return (
<Frame
head={<link rel="stylesheet" type="text/css" href="style.css" />}
scrolling="no"
>
<ChatWidget />
</Frame>
);
}
有了这个,我得到了无样式内容的可怕闪光。我认为这是因为包括 <ChatWidget>
在内的所有内容都在 css 可以完全下载之前呈现。
有没有一种方法可以确保 CSS 在所有内容呈现之前下载?
此外,不确定这是否重要,但我正在使用 Preact。
我最终编写了自己的 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>
);
}
}
正在处理一闪而过的无样式内容问题。我有一个注入到用户页面的聊天小部件。这样我就不会与现有样式发生冲突。我正在使用 react-frame-component
在 iframe 中呈现。这工作得很好,但我遇到的一个问题是 CSS.
react-frame-component
接受一个道具 head
,您可以使用它来将 link 传递给样式表。使用 MiniCSSExtractPlugin,我能够将我的 css 放入一个单独的文件中,然后我可以 link 到:
render(props, state) {
return (
<Frame
head={<link rel="stylesheet" type="text/css" href="style.css" />}
scrolling="no"
>
<ChatWidget />
</Frame>
);
}
有了这个,我得到了无样式内容的可怕闪光。我认为这是因为包括 <ChatWidget>
在内的所有内容都在 css 可以完全下载之前呈现。
有没有一种方法可以确保 CSS 在所有内容呈现之前下载?
此外,不确定这是否重要,但我正在使用 Preact。
我最终编写了自己的 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>
);
}
}