我有一个多步骤表单,我使用react-router在不同步骤之间导航。 在部分步骤中,我向用户展示了iframe。 当用户在步骤之间导航时,它总是卸载并重新安装iframe,这会导致两个问题:
有没有办法将iframe实例保留在某个全局存储中,并且只在必要时才将其挂载到DOM?
其他任何想法如何解决这个问题?
感谢。
答案 0 :(得分:5)
有没有办法将iframe实例保留在某个全局存储中 只在必要时将它挂载到DOM?
是的,你可以,但如果你甚至从DOM中删除iframe并在以后重新附加它仍然会重新加载,所以这样问题实际上与React的组件树几乎没什么关系。你真正需要的只是隐藏你的iframe并在以后再次显示它。
您当然可以隐藏并在React中显示iframe:
{ <iframe src="..." style={{display: this.state.showing ? "block" : "none"}} /> }
在这种情况下,您需要在 not 卸载的某个位置渲染iframe。您可以使用树中更下方的组件向上通信以显示/隐藏iframe。
但是,如果您真的希望能够隐藏/显示组件树中不同位置的iframe,可以安装和卸载,但是它会变得相当棘手而不是React的典型用例。
您需要自己创建DOM iframe,并将其附加到React组件树之外的DOM中(这通常是React中的反模式)。然后,您可以使用代理组件在安装和卸载时显示/隐藏此DOM元素。
这是一个将iframe附加到document.body
并在安装组件时显示iframe并在卸载组件时隐藏它的示例:
class WebView extends React.Component {
static views = {};
componentDidMount() {
if (!WebView.views[this.props.url]) {
WebView.views[this.props.url] = this.createWebView(this.props.url);
}
WebView.views[this.props.url].style.display = "block";
}
componentWillUnmount() {
WebView.views[this.props.url].style.display = "none";
}
createWebView(url) {
let view = document.createElement("iframe");
view.src = this.props.url;
document.body.appendChild(view);
return view;
}
render() {
return null;
}
}
Here it is working on CodePen:请注意,当您隐藏(卸载)然后显示(装载)WebView
iframe状态(例如搜索输入)保持不变时。
您还需要对iframe的位置和大小进行正确显示。我没有表现出来,因为一般来说解决起来有点困难。
请注意,此解决方案类似于"portal" pattern。这里的区别是不要卸载iframe以保持其状态并防止重新加载。
答案 1 :(得分:2)
很简单,如果未渲染父级,则无法在渲染树中保留组件。也就是说,当路线发生变化时,如果您的组件是Route
的子项,则必须卸载该组件。
侧面步骤的一种方法是使您的组件不是任何路径的孩子。通过这种方式,您将始终在每个路由中将此组件与一起呈现。然后,您可以在适当的时候使用样式来显示/隐藏它。显然,这将部分地破坏DOM的结构。