【问题标题】:dom ready event in ReactReact 中的 dom 就绪事件
【发布时间】:2016-12-03 16:04:30
【问题描述】:

我有一些组件如下:

包装器:包装加载器和页面

加载器:一些动画

页面:页面内容

这样的代码:

<body>
  <div id="app"></div>
</body>

class Loader extends Component {}

class Page extends Component {}

class Wrapper extends Component {
    render() {
        return (
            <Loader/>
            <Page />
        );
    }
}

ReactDOM.render(<Wrapper />, document.getElementById('app'));

我想在 DOM 完全加载后隐藏 Loader 并显示 Page 组件。

我应该如何在 React 中编写 dom 就绪事件?

喜欢 jQuery:$(window).on('ready')

【问题讨论】:

    标签: reactjs domready


    【解决方案1】:

    TL;DR 如果我理解正确,答案可能是“不可能”。但是还有另一种解决方案...

    这就是我认为您正在尝试做的事情,描述为一系列步骤:

    1. 页面开始加载,&lt;Loader /&gt; 组件显示“页面加载”动画

    2. 页面加载完成,&lt;Loader /&gt; 组件被移除(或隐藏),&lt;Page /&gt; 组件与“真实”页面内容一起插入(或显示)。

    问题出在这里:请记住,您将 React 组件注入到页面中,如下所示:

    ReactDOM.render(<Wrapper />, document.getElementById('app'));
    

    在加载 DOM 之前,您实际上无法注入 React 组件。所以到那时,&lt;Loader /&gt; 要么出现大约 2 毫秒然后消失,要么根本不出现(因为 DOM 在注入页面时已经加载)。

    如果你想展示一个 throbber 或其他简单的动画(如 GIF 动画),我会尝试一种混合方法:

    像这样设置你的 HTML:

    <body>
        <div id="app"><img src="throbber.gif" /></div>
    </body>
    

    在您的脚本标签中,包含一个 JQuery“文档就绪”事件处理程序以加载 React 组件:

    class Page extends Component {}
    
    class Wrapper extends Component {
        render() {
            return (
                <Page />
            );
        }
    }
    
    $(document).ready(function () {
        ReactDOM.render(<Wrapper />, document.getElementById('app'));
    });
    

    请注意,我忽略了&lt;Loader /&gt; - 颤动图像正在执行加载程序的工作。

    这里的想法是,当页面加载时,跳动的 GIF 会跳动,直到 DOM 加载完毕,此时 JQuery 的文档就绪事件将触发,div#app 的内容将被替换。

    我还没有尝试过,但它应该工作,前提是 React 实际上替换 div#app 的内容,而不是仅仅向其附加内容。如果不是这种情况,那么只需将文档就绪处理程序更改为如下所示:

    $(document).ready(function () {
        $('div#app img').remove();
        ReactDOM.render(<Wrapper />, document.getElementById('app'));
    });
    

    【讨论】:

    • 这行得通,React 将替换其挂载点的内容。重要的是,加载器所依赖的任何 CSS 在 React 挂载之前都可用,因此可能需要一个内联 &lt;style&gt; 块,其中包含足够的 CSS 用于初始渲染。
    • 不需要 Jquery,因为你可以使用 document.addEventListener("DOMContentLoaded", function(event) { }
    • 你现在应该使用 React Suspense 和 React Lazy,效果会好很多。
    【解决方案2】:

    我最终使用的方法(不需要 JQuery)如下:

    在 index.html 中,将 loader 元素放在根 div 之后

    <div id="root">
    </div>
    <div id="preloader" class="pre-loader">
      <img src="..."> </img>
    </div>
    

    然后在你的 index.js 中:

    document.addEventListener("DOMContentLoaded", function(event) { 
      
      ReactDOM.render(
        <React.StrictMode>
          <Provider store={store}>
        <BrowserRouter>
          <DashApp />
        </BrowserRouter>
        </Provider>
        </React.StrictMode>,
        document.getElementById("root")
      );
    
      const loadingScreen = document.getElementById("preloader");
       loadingScreen.style.opacity = 0;
       loadingScreen.style.display = "none";
    });
    

    所以基本上我们只是遵循与其他答案建议类似的方法,但不需要 JQuery,因为我们使用侦听加载事件

    document.addEventListener("DOMContentLoaded", function(event) { }
    

    另一种方法是将加载器放在根 div 中,这意味着 React 在加载时默认会覆盖它:

    <div id="root">
      <div id="preloader" class="pre-loader">
        <img src="..."> </img>
      </div>
    </div>
       
    

    我个人的完整做法可以看这个

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-16
      • 2015-04-12
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 2020-05-30
      相关资源
      最近更新 更多