FLIP 是什么呢?
已经有很多文章介绍过 FLIP,大名鼎鼎的 vue 里面的 transition-group,使用的也是 FLIP
参考 Github 地址:github.com/googlearchi…
通过官方文档,我们大概了解了 FLIP 的流程
主要概括为 四个步骤:
- First(元素初始状态)
- Last(元素完成状态 - Layout Change)
- Invert(状态反转操作)
- Play(播放动画)
通过上述四个步骤,可以帮助开发者轻松实现过渡效果,几乎不用额外代码的情况下,可以实现复杂的过渡动画效果
主要疑问
第二个步骤,即 Layout Change 以后,还能继续显示动画吗?
例如,一辆车已经到达了目的地以后,再去显示一次这辆车从 出发地 到 目的地 的动画
像上面的描述那样操作元素,我们看到的动画就会很奇怪:车闪现到了目的地,然后再闪回起点,再从起点 以动画的方式去到 目的地
带着这个疑问去看相关的源码
查看源码后发现,果然是 车 已经到达目的地后,再把 车 重新从 出发地 到 目的地的过程绘制出来
如上图,当车到达目的地,layout 更新后,还没刷新到屏幕前,把 车 设置回出发地,然后再把 车 从出发地 到 目的 的运动过程 绘制出来
做个实验
修改 FLIP 源码,在接口 wrap 方法中,this.flip 的流程上,添加个 setTimeout 或者 requestAnimationFrame 处理,看看会出现什么情况
修改前:
修改后:
“汽车” 先出现在了 目的地,然后瞬间被搬回 出发地,然后再出发 至 目的地
总结关键流程
元素样式更新后,立刻 同步 进行 layout 更新(通知浏览器,让浏览器更新元素的位置信息,但由于还没释放 js 线程,浏览器还不会把 元素 的新位置 更新到屏幕上)
layout 更新后,即可获得各元素新的表现信息(位置,宽高等)(获得车在终点的位置信息)
同步执行 再一次更新元素的样式表现(把车放回原点)
拓展思考
活用 浏览器重排(reflow 更新 layout 信息),我们可以实现 类似 “预渲染” 的能力
在 FLIP 中,通过 getBoundingClientRect 接口,完成了一次 layout 的更新
在同一次的 task 中,layout 的更新只会实际执行一次,所以 FLIP 源码中的多次使用 getBoundingClientRect 并不会引起多次 reflow 从而导致页面性能下降的问题
FLIP 无法实现元素 删除前后(卸载)的过渡效果
目前前端主流的 过渡方案 有两种:
- 过渡模式
- FLIP
FLIP 主要用于 layout 更新时的自动过渡
过渡模式(before-enter、enter-active、active、before-leave、leave-active)则可以实现单个元素在声明周期中的细节过渡
相比之下,
FLIP 可以实现 layout 的自动过渡,而过渡模式则不行
过渡模式支持 元素生命周期过渡效果,而 FLIP 则不行
如果想要实现 支持 元素生命周期过渡 以及 layout 更新自动过渡的效果,就有必要考虑将 过渡模式 以及 FLIP 合并一起使用
Vue 的过渡方案 transition-group 就实现了合并的效果