Vuejs 过渡 css 只向下滑动
Posted
技术标签:
【中文标题】Vuejs 过渡 css 只向下滑动【英文标题】:Vuejs transition css only slide down 【发布时间】:2021-01-18 21:04:03 【问题描述】:我一直在寻找这个问题的解决方案很长时间,但我似乎找不到这个问题的最佳解决方案。基本上我有一个手风琴,当用户打开它时,它应该轻轻滑下并有一个很好的过渡。
我很确定只有 css 才能做到这一点。如果我错了,请纠正我,但 css 转换在性能方面比 js 转换更好。
所以现在是我面临的问题的 html:
<transition name="slide-down">
<ul v-if="isDisplayingOpeningHours" class="mt-2 text-sm flex flex-col space-y-2">
<li v-for="i in 10" :key="i"> <!-- just for testing purposes -->
element
</li>
</ul>
</transition>
而css是:
.slide-down-enter-active, .slide-down-leave-active
transition: all .5s;
.slide-down-enter-to, .slide-down-leave
overflow: hidden;
max-height: 100%;
.slide-down-enter, .slide-down-leave-to
overflow: hidden;
max-height: 0;
这会导致过渡不流畅。滑下来好像没什么问题,但是滑上去就真的很卡顿,一点都不流畅!如果我设置max-height: 10rem
它并没有让它变得更好。我希望有人可以调试帮助我解决这个问题,也许可以教我更多关于 vue 转换和 js 与 css 转换的知识。
编辑: 只是为了澄清过渡本身应该只由 css 完成。手风琴的开口是用js的,很好。另外,如果能看到一个使用原生 vue-transition 组件的过渡示例,那将是一件好事。
编辑 2: 这是一个与我有同样问题的代码框。 https://codesandbox.io/s/frosty-bash-lmc2f?file=/src/components/HelloWorld.vue
【问题讨论】:
所以你只是在寻找一个 CSS only 下拉菜单。平稳过渡? @GarthBaker 不只是一个常规的下拉菜单,其中的过渡是一个平滑的仅 css 过渡。 【参考方案1】:另一个更新!!! 为了实现JS过渡大家可以看看official document来学习。无论如何,我不打算实现花哨的计时机制,但在最简单的形式中,React 中的 JS 折叠转换看起来像下面这样,我将它包含在现有的 codesandbox 中:
<template>
...
<div>
<button @click="jsOpen = !jsOpen">Open JS list</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:level-cancelled="leaveCancelled"
v-bind:css="false"
>
<ul v-if="jsOpen" class="mt-2 text-sm flex flex-col space-y-2">
<li v-for="i in 10" :key="i">item- i </li>
</ul>
</transition>
</div>
</template>
<script>
export default
...
methods:
beforeEnter(el)
el.style.height = 0;
el.style.overflow = "hidden";
,
enter(el, done)
const increaseHeight = () =>
if (el.clientHeight < el.scrollHeight)
const height = `$parseInt(el.style.height) + 5px`;
el.style.height = height;
else
clearInterval(this.enterInterval);
done();
;
this.enterInterval = setInterval(increaseHeight, 10);
,
afterEnter(el) ,
enterCancelled(el)
clearInterval(this.enterInterval);
,
beforeLeave(el) ,
leave(el, done)
const decreaseHeight = () =>
if (el.clientHeight > 0)
const height = `$parseInt(el.style.height) - 5px`;
el.style.height = height;
else
clearInterval(this.leaveInterval);
done();
;
this.leaveInterval = setInterval(decreaseHeight, 10);
,
afterLeave(el) ,
leaveCancelled(el)
clearInterval(this.leaveInterval);
,
,
;
</script>
更新: 在了解了 OP 的要求后,我试图玩不同的东西,我偶然发现了this article on css-tricks,它解释了有关转换的更多细节,从那篇文章中提出的另一个非 js 解决方案如下所示,我将它包含在现有的 @ 987654324@:
.scale-enter-active,
.scale-leave-active
transform-origin: top;
transition: transform 0.3s ease-in-out;
.scale-enter-to,
.scale-leave-from
transform: scaleY(1);
.scale-enter-from,
.scale-leave-to
transform: scaleY(0);
这里不是高度,而是在 y 轴上缩放。 IT 还具有副作用,它首先将容器扩展为完整大小,然后更新(缩放)内容。
Vue v3.x
V3 中的 -leave
和 -enter
类重命名为 -leave-from
和 -enter-from
。看看这个stackblitz。
.slidedown-enter-active,
.slidedown-leave-active
transition: max-height 0.5s ease-in-out;
.slidedown-enter-to,
.slidedown-leave-from
overflow: hidden;
max-height: 1000px;
.slidedown-enter-from,
.slidedown-leave-to
overflow: hidden;
max-height: 0;
Vue v2.x
问题是您将 max-height
指定为 100%,请使用一些大于您预期的最大高度的值。将您的样式更新为:
.slide-down-enter-active,
.slide-down-leave-active
transition: max-height 0.5s ease-in-out;
.slide-down-enter-to,
.slide-down-leave
overflow: hidden;
max-height: 1000px;
.slide-down-enter,
.slide-down-leave-to
overflow: hidden;
max-height: 0;
它应该可以工作。看看这个codesandbox 演示。
【讨论】:
好的,我可以将高度设置为自动吗?因为我不想设置固定高度。 @Ezrab_ 你可以,但它不会工作,因为它需要一些高度值。为什么没有可滚动的固定高度容器? 好吧,因为它不应该是可滚动的。从示例中也可以看出,它仍然不流畅。 (我已经实现了你给我的解决方案)gyazo.com/020835748ef0443fd4f4f76db8321d0e @Ezrab_ 更新了我的答案,技巧是将 max-height 用于具体值,这将超过您预期的最大高度。 当然,它只是增加和减少元素样式,为了提高速度,您更新setInterval
以使用较小的值并减少使用较大的值。稍后我会看看并更新codeandbox。以上是关于Vuejs 过渡 css 只向下滑动的主要内容,如果未能解决你的问题,请参考以下文章
我怎样才能实现像jQuery的slideDown一样的向下滑动效果,但只使用CSS?