React 动画组件实现思路
最近写了一个 React 动画组件,在这里记录一下实现的思路。
动画组件参考了 React 官方的实现和 React-Component 的 Animate 组件,这两个组件的实现思路大同小异。
假设这个组件的名称为 Animator
,使用形式类似于下面这样:
在 Animator
包裹后,当新插入 item,删除 item 的时候,会有动画产生。
主要的思路是,Animator
组件内部有一个 state
来保存将要渲染的 children,当有新的 children 进来的时候(以 props
的方式,会将 state
中的 children 和新的 children 进行合并,这期间(即 componentWillReceiveProps
),又要决定哪些元素是要进行入场动画的,哪些元素是要进行出场动画的,然后重新渲染,渲染结束之后,再对 children 进行动画操作。
简单来说, Animator
提供了一个缓冲区,在元素实际上是要删除的时候,Animator
通过 state
将其保存住,在做完动画之后才真正地删除。
接下来我们再更加细致地看看这个 Animator
该如何实现。
在 componentWillReceiveProps
这个生命周期中,会传入新的 props
,因此我们可以拿到接下来要展示的 children(命名为 nextChildren
),另外就是 state
保存着的 children (命名为 prevChildren
),然后我们执行一个 mergeChildren
的操作,将 prevChildren
和 nextChildren
进行合并,接着,找出所有需要进行入场动画的孩子节点,也就是在 nextChildren
中但是不在 prevChildren
中的节点,以及所有需要进行离场动画的孩子节点,也就是在 prevChildren
中但是不在 nextChildren
中的节点,我们将这些节点分别用 keysToEnter
和 keysToLeave
保存。至于如何找到这些节点,我们规定,使用该组件的话,所有孩子节点都需要指定一个与其他孩子不同的 key
属性,这样就可以轻松找到节点了。
那么,节点要怎么进行合并呢?
以上就是合并两个孩子节点数组的方法,findChildByKey
方法根据 key 值在一个孩子节点数组中寻找,寻找成功返回 true
,否则返回 false
,相信大家很容易就能看懂是怎么实现的(在纸上模拟一下情况就知道了)。
接着就是要在 componentDidUpdate
这个生命周期方法中写一些代码了,我们根据之前保存的 keysToEnter
和 keysToLeave
所对应的节点进行相应的动画操作,我们可以约定孩子节点可以实现类似 componentWillEnter
,compoenntDidEnter
之类的方法,然后我们就可以在适当的时候去调用这些方法。需要注意的是,在离场动画结束之后,需要将该离场了节点从 state
中删除,这样才符合逻辑。
另外,在实现这个组件的时候犯了个小错误:
该函数不会修改原数组,之前使用该方法忘记赋值,然后程序出现逻辑上的错误,找了好久才发现,一定要牢记在心。
顺便说一说
该函数会修改原数组,并且会返回新的数组长度。