【问题标题】:Keep components between routes using react-router使用 react-router 在路由之间保留组件
【发布时间】:2016-09-15 00:35:32
【问题描述】:

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

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

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

还有其他解决这个问题的方法吗?

谢谢。

【问题讨论】:

    标签: iframe reactjs react-router


    【解决方案1】:

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

    是的,你可以,但是如果你甚至从 DOM 中删除一个 iframe 并稍后重新附加它,它仍然会被重新加载,所以这样问题实际上与 React 的组件树几乎没有关系。您真正需要的是隐藏您的 iframe 并稍后再次显示。

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

    { <iframe src="..." style={{display: this.state.showing ? "block" : "none"}} /> }
    

    在这种情况下,您需要在 没有 被卸载的某个地方渲染 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;
      }
    }
    

    Here it is working on CodePen:请注意,当您隐藏(卸载)然后显示(安装)WebView 时,iframe 状态(例如搜索输入)保持不变。

    您还需要调整 iframe 的位置和大小,以正确显示在您的布局中。我没有展示这个,因为它一般很难解决。

    请注意,此解决方案类似于"portal" pattern。这里的区别是永远不要卸载 iframe 以保持其状态并防止重新加载。

    【讨论】:

      【解决方案2】:

      很简单,如果父组件未渲染,则无法在渲染树中保留组件。也就是说,当路由改变时,如果你的组件是Route 的子组件,那么它必然会被卸载。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 2017-04-24
        • 1970-01-01
        • 2017-06-18
        • 1970-01-01
        • 2019-09-01
        • 2020-01-03
        相关资源
        最近更新 更多