使用react-router在路由之间保留组件

E. *_*mon 6 iframe reactjs react-router

我有一个多步骤的表单,我正在使用react-router在不同的步骤之间导航.在某些步骤中,我向用户显示iframe.当用户在步骤之间导航时,它总是卸载并重新安装iframe,这会导致两个问题:

  1. 它从其源重新加载iframe,这使它跳转.
  2. 由于它是一个iframe,我无法控制其内部状态,并且它会失去步骤之间的状态.因此,如果用户对iframe有一些输入,则在移动到下一步时输入会丢失.

有没有办法将iframe实例保留在某个全局存储中,并且只在必要时将其挂载到DOM?

任何其他想法如何解决这个问题?

谢谢.

Aar*_*all 5

有什么方法可以将iframe实例保留在某些全局存储中,并仅在必要时将其安装到DOM上?

是的,您可以,但是如果您甚至从DOM中删除一个iframe并在以后重新添加它,它仍然会被重新加载,因此通过这种方式,问题实际上与React的组件树几乎没有关系。您真正需要的只是隐藏您的iframe,稍后再显示。

您当然可以像这样在React中隐藏和显示iframe:

{ <iframe src="..." style={{display: this.state.showing ? "block" : "none"}} /> }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,你需要渲染的iframe在一些地方,它没有得到卸载。您可以使用树中更下方的组件向上向上通讯以显示/隐藏iframe。


但是,如果您确实希望能够从已安装和卸载的组件树中的不同位置隐藏/显示iframe ,则可以,但是它有点棘手,而不是React的典型用例。

您需要自己创建DOM iframe,并将其附加到React组件树之外的DOM中的某个位置(这通常是React中的反模式)。然后,您可以使用代理组件在挂载和卸载时显示/隐藏此DOM元素。

这是一个将iframe附加到的示例,document.body并在安装组件时显示它,而在卸载组件时隐藏它:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是在CodePen上运行的:请注意,当您隐藏(卸载)然后显示(装载)时WebView,iframe状态(例如搜索输入)保持不变。

您还需要调整iframe的位置和大小,以使其正确显示在布局中。我没有显示出来,因为通常很难解决。

请注意,此解决方案类似于“门户”模式。此处的区别是,永远不要卸载iframe来保持其状态并防止重新加载。


fir*_*oit 2

很简单,如果未渲染父组件,则无法在渲染树中保留组件。也就是说,当路由更改时,如果您的组件是某个组件的子组件,则该组件必然会被卸载。Route.

避免这种情况的一种方法是使您的组件根本不是任何 Route 的子组件。这样,您将始终在每条路线旁边渲染该组件。然后您可以简单地使用样式在适当的时候显示/隐藏它。显然,这会部分损害 DOM 的结构。