交互动画系列之一:解决bundle.js首次加载动画问题

@youngwind 2016-04-06 08:08:24发表于 youngwind/blog React

系列说明

嗯,要想成为一个专业的前端,不懂交互动画可不行。所以借着做项目,顺便好好研究一下这个方向,希望能给团队带来一些提升。

本篇要解决的问题

如果你用react+webpack做过单页面应用,那么你一定遇到过bundle.js太大导致首次加载时白屏时间过长,解决办法有几个方向。

  1. 从较少bundle.js体积大小入手
  2. 从服务端渲染入手
  3. 从加载中动画入手

首次尝试

一开始我是这么想的:既然bundle.js还没加载完,那么我就把动画的DOM和CSS写在index.html里面就好了。

// index.html
<style>
// 加载中的动画样式
</style>

<div id='root'>
  // 添加一些加载中的动画DOM元素
</div>

结果:

  1. 在bundle.js加载完成之前确实会显示动画。
  2. 但是,一旦bundle.js加载完成,动画会瞬间消失,毫无过渡。

究其原因,无非是react在首次渲染真实DOM元素之前,会清空root里面的DOM元素。

再次尝试

找到原因之后我转换了一下思路:我能不能捕获到react即将渲染真实DOM元素,然后在那之前进行处理呢?比如这样子

// 顶层的container

componentWillMount:function(){
  // 给Index.html里面的动画元素提供淡出动画
}

事实证明此方法不可行。在执行到这儿的时候,我根本找不到让react组件延时挂在到真实DOM的入口,也就是如何在WillMount和Mount之前设置一个setTimeout,我找不到方法。

再接再厉

后来忽然想到一种方法,那就是把动画元素放在root之外,这样react就能自由地控制了

// index.html
<style>
// 加载中的动画样式
</style>

<div id='root'></div>
<div id='loading'>
  // 添加一些加载中的动画DOM元素
  // 这些DOM元素是绝对定位的,覆盖了root
</div>

然后,在componentDidMount之后给loading添加消退动画,这样子就可以实现了。
而且,通过这种方法,你可以精确地控制loading遮罩层的消退时机。实际上我在应用的时候不是在componentDidMount的时候就消退的。因为我里面有数据请求,而这个数据请求至关重要,没有数据展示该页面根本没有意义。所以我索性将消退时机推迟到数据返回成功。这样做的好处有两个。

  1. 用户正式进入应用的时候应用已经是可用的状态了
  2. 不需要再进入应用之后再做数据加载中的动画

最后给个截图
demo