Vue Transition
事件起因
因需求关系,要求做到添加购物车时,有个小球从点击添加的按钮通过运动轨迹到达购物车位置, 因为是需要获取动态位置, 通过css渲染动画
心有余而力不足, 很幸运的是, vue-transition内置组件提供js钩子函数
, 为我提供完成的动画的保障
实践
首先, 让我们了解下vue transition的一些特性:
Props:
name - string,用于自动生成 CSS 过渡类名。例如:name: 'fade' 将自动拓展为.fade-enter,.fade-enter-active等。默认类名为 "v"
appear - boolean,是否在初始渲染时使用过渡。默认为 false。
css - boolean,是否使用 CSS 过渡类。默认为 true。如果设置为 false,将只通过组件事件触发注册的 JavaScript 钩子。
type - string,指定过渡事件类型,侦听过渡何时结束。有效值为 "transition" 和 "animation"。默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。
mode - string,控制离开/进入的过渡时间序列。有效的模式有 "out-in" 和 "in-out";默认同时生效。
duration - number | { enter: number, leave: number } 指定过渡的持续时间。默认情况下,Vue 会等待过渡所在根元素的第一个 transitionend 或 animationend 事件。
enter-class - string
leave-class - string
appear-class - string
enter-to-class - string
leave-to-class - string
appear-to-class - string
enter-active-class - string
leave-active-class - string
appear-active-class - string
事件:
before-enter
before-leave
before-appear
enter
leave
appear
after-enter
after-leave
after-appear
enter-cancelled
leave-cancelled (v-show only)
appear-cancelled
具体的一些使用方法,因为与本文内容不是很贴边,在这里不详细讲了 剩余的就不在这里说了, 开始主题
举个例子更加让人了解问题
不知道大家在写原生js的时候,有没有遇到过这样的一个问题
一个DOM元素从display: none变为display: block的时候,想要它想vue的transition一样,利用动画过渡过来, 你很有可能会这么写
<div class="c-transition__container" style="display: none;"></div>
.c-transition__container {
width: 100px;
height: 100px;
background: red;
transition-duration: .5s;
transition-property: transform;
}
const oDiv = document.getElementsByClassName('c-transition__container')[0]
document.onclick = function() {
oDiv.style.transform = 'translate3d(100px, 0, 0)'
oDiv.style.display = 'block'
}
事实总是难以接受, 这么写是不会有平滑过渡的效果,而是直接在最终的位置显示
沮丧的你从此弃坑,发誓再也不碰前端:laughing:
别着急, 下面讲解如何实现从0到1的平滑
首先我们要了解浏览器的渲染时机
for(let i = 0; i < 100; i++) {
oDiv.style.transform = 'translate(100px, 0, 0)'
}
以上的for循环语句里操作了100次的div, 但实际上浏览器并不会渲染100次, 根据上文
我们可以得知, 浏览器的UI Render是在每个macroTask最后清空microTask队列后才会触发一次, 但是浏览器会根据实际情况来确定是否需要渲染, 通常在每隔16.7ms的情况下会渲染一次, 在此期间,浏览器会将所有的DOM操作推入到队列
中,在进行渲染的时候会一个一个取出,直到清空队列。
浏览器渲染过程:
JavaScript:JavaScript 实现动画效果,DOM 元素操作等。(Cpu)
Style(计算样式):确定每个 DOM 元素应该应用什么 CSS 规则。(Cpu)
Layout(布局):计算每个 DOM 元素在最终屏幕上显示的大小和位置。由于 web 页面的元素布局是相对的,所以其中任意一个元素的位置发生变化,都会联动的引起其他元素发生变化,这个过程叫 reflow。(每个DOM对应一个渲染层)(Cpu)
Paint(绘制):在多个层上绘制 DOM 元素的的文字、颜色、图像、边框和阴影等, 这个过程叫做repaint。(Cpu)
Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。(进入GPU)(render Tree 解析渲染)
理解了以上部分, 那么接下来的问题就好办了
我们逐句分析刚才的案例:
- 首先我们初始化了div的一些基本状态, 包括宽高, transition等一些css样式
- 在点击document的时候,我们将div的style复制为了
translate(100px, 0, 0)
,并且更新了状态display: block
, 注意这个时候, 也就是我刚才提到的浏览器, 并没有进行直接进行渲染,而是将它推入到了队列里, 但记得一句, DOM Tree是实时更新的, 此时虽然没有渲染,但是DOM Tree里的状态已经更新了,这个时候DOM transform已经变成了100px, 当真正渲染的时候, 是从100px变为100px,并不是从0变成100px,所以我们看到的是没有过渡效果的。
解决方案
从以上的分析,我们可以基本了解为什么会是这种现象, 下面我来讲下解决方案:
-
首先就是大家所熟知的setTimeout,这个的确可以解决以上问题, 但是setTimeout属于macroTask, 每个task的最后都会触发一次UI Render, 以上操作会造成多次渲染, 所以并不推荐使用
-
(推荐) 强制浏览器清空队列进行渲染操作
在获取布局信息操作的时候, 会强制浏览器清空队列进行渲染, API有以下几个: innerHeight、scrollTop、offsetHeight、getBoundingClientRect等等
这个时候, 浏览器
重新进行回流重绘渲染
操作, 这个时候触发DOM操作都可以得到有效回馈
总结
Vue transitionjs钩子函数其实就是原生js写的动画, 同样从无到有进行平滑, 你学会了吗?
今天的文章别再说Transition 无法过渡display了分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18616.html