【问题标题】:Prevent Component from Unmouting when Routing路由时防止组件卸载
【发布时间】:2017-10-03 20:32:37
【问题描述】:

我有一个子组件,在从父组件路由时需要保留它。 在网上搜索关于“react-router”的大多数答案,但我使用的是“react-router-dom”(又名 React Router V4)。 我很新的反应,并认为这应该很简单,比如将组件标记为不被卸载或类似的东西。

import Home from "./home/Home";
import Top from "./top/Top";

export default class Layout extends React.Component{
    render(){
        return(
            <Router>
                <div class="wrp">
                    <Menu/>
                    <section class="left">
                        <Header/>
                        <Switch>
                            <Route exact path="/" component={Home} />
                            <Route exact path="/top" component={Top} />
                        </Switch>
                        <Footer/>
                    </section>
                </div>
            </Router>
        );
    }
}

在“Home”组件内部有一个子组件需要留在 DOM 中。

应要求 Home 和子组件代码:

import React from "react";

import Sponsor from "./Sponsor";
import Feature from "./Feature";
import Top from "./Top";
import Discord from "./Discord";
import Middle from "./Middle";

export default class Home extends React.Component{
    render(){
        return(
            <section class="main_wrp">
                <Sponsor/>
                <div class="bulk">
                    <Feature/>
                    <div class="co6">
                        <Top/>
                        <Discord/>
                    </div>
                    <Middle/>
                </div>
            </section>
        );
    }
}

子组件(Discord):

import React from "react";

export default class Discord extends React.Component{

    render(){
        return(

            <div class="DiscordViewer">
                <embed height='500px'src='https://somelink.com' />
            </div>
        );
    }
}

【问题讨论】:

  • 如果你想离开 Home 但仍然显示 Home 的孩子,我认为孩子需要在 Home 组件之外。可以贴一下 Home 组件和 Child 组件的代码吗?
  • @palsrealm 添加了请求的代码。

标签: javascript reactjs components react-router-v4


【解决方案1】:

在不修改组件树的情况下,在离开其父节点后保留叶节点组件(本例中为 Discord)将违反树的定义。您不能简单地使用 CSS 隐藏和重新定位组件,您必须对树的整个分支执行此操作,从最近的父节点开始,导致该叶节点。这可能会导致不必要的复杂性和较差的性能,尽管可以这样执行:

const HomeWrapper = withRouter(props => (
  <div style={props.location.pathname !== '/' ? {display: 'none'} : {}}>
    <Home {...props} />
  <div>
))

<HomeWrapper />
<Switch>
  <Route exact path="/top" component={Top} />
  <Route exact path="/other" component={OtherComponent} />
</Switch>

如果您的组件结构灵活,您可以将 Discord 组件从主路由移出到隐藏的 div 中。然后,您将使用非反应 DOM 操作来移动外部隐藏 div 和 Home 中显示的 div 之间的不和谐。在您的 Home 组件中,您可以呈现如下所示的 DiscordWrapper 组件。您需要从 shouldComponentUpdate 返回 false 以阻止更新。 :

<div id='discord-wrapper-external' style={{display: 'none'}}>
  <Discord id='discord-dom-node'/>
</div>

class DiscordWrapper extends React.Component {
  componentDidMount() {
    this.el = document.getElementById('discord-dom-node')
    document.getElementById('discord-wrapper-internal').appendChild(this.el)
  }
  shouldComponentUpdate() {
    return false
  }
  componentWillUnmount() {
    document.getElementById('discord-wrapper-external').appendChild(this.el)
  }
  render() {
    return <div id='discord-wrapper-internal' />
  }

【讨论】:

    【解决方案2】:

    一种可能的方法是将&lt;Discord\&gt; 组件从主页中取出。 因此,在 Layout 中,您创建 &lt;Discord\&gt; 组件并将其作为子组件传递给所有其他组件。

    布局

    export default class Layout extends React.Component{
        render(){
            let discord = <Discord/>;
            return(
                <Router>
                    <div class="wrp">
                        <Menu/>
                        <section class="left">
                            <Header/>
                            <Switch>
                                <Route exact path="/" render={()=><Home>{discord}</Home>} />
                                <Route exact path="/top" render={()=><Top>{discord}</Top>} />
                            </Switch>
                            <Footer/>
                        </section>
                    </div>
                </Router>
            );
        }
    }
    

    您的 Home 组件将变为

    export default class Home extends React.Component{
        render(){
            return(
                <section class="main_wrp">
                    <Sponsor/>
                    <div class="bulk">
                        <Feature/>
                        <div class="co6">
                            <Top/>
                            {this.props.children}
                        </div>
                        <Middle/>
                    </div>
                </section>
            );
        }
    }
    

    您还可以将&lt;Discord/&gt; 组件作为命名道具传递给所有需要显示它的组件,而不是将其作为子组件传递。

    【讨论】:

    • 感谢您的回复,这无济于事,因为我试图避免每次回家时都加载 Discord 组件。 Discord 组件是一个非常重的嵌入,应该加载一次。所以我的计划是在客户不在主页时对其进行样式设置。 (绝对位置,不透明度 0)
    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 2023-01-10
    • 2015-10-10
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多