1. 内存泄露
- 我测试的是AE文件导出的lottie文件(单个动画对象包含3个蒙版,3-5个元素,无渐变颜色,动画时长1s。一共有3-4个这样的动画对象),这样的动画如果不对lottie生成的对象进行销毁的话,经过测试存在内存泄露问题,不使用缓存机制,会导致长时间使用下,内存占用持续走高:
- 这里使用单实例模式,缓存anim对象的引用,可以平衡内存的使用。
// Singleton if (anim) { anim.doSth(); } else { anim = lottie.loadAnimation(data); }
- 结果如图,没有内存占用持续走高的现象发生:
2. 帧误差
- 在调用, anim.play()方法后,动画会从第0帧执行到最后一帧停止,正常情况下是不会出问题的。
- 但是在暴力测试下,如果频繁触发动画执行,会导致终点动画的结束帧有误差,比如我做的60帧的动画,在暴力测试下,会导致终点帧为59帧,如图:
- 这样的话,下次再执行anim.play方法时,是从第59帧执行到60帧,而不是从第0帧执行到第60帧(即replay),所以这里需要定义一个方法使其replay。
const replay = (anim: AnimationItem) => { if (anim.currentFrame !== anim.totalFrames) anim.goToAndStop(anim.totalFrames, true); anim.play(); };
3. 销毁方式
- 这里在销毁的地方,effect hook上踩了一个坑,location会因为路由变化,重新触发effect hook。
- 这里需要注意,如果一个effect同时包含return函数和refs的时候,如果refs变化,那么这时return函数会执行,以清除上一次effect。
- 所以因为location的变化,在当前这个effect hook里,我把anim给销毁了,那么就会存在一些判断逻辑上的缺漏!!
- 所以最好的hook使用方式,应该是将会有相互影响的hook分开来写,创建/销毁应该清晰化去处理,这样才不会产生连串效应。
const location = useLocation(); // react router dom
// wrong way
useEffect(() => {
// add event listener on location's change events
// ... deal events
return () => {
anim && anim.destroy()
}
}, [location])
// correct way
useEffect(() => {
// add event listener on location's change events
// ... deal events
}, [location])
useEffect(() => {
return () => {
anim && anim.destroy()
}
}, [])
4. 结束语
- 如果觉得写的不错,有用的话,还请帮我点个赞 O(∩_∩)O
- 转发请注明出处,谢谢!