我正在努力尝试用v-if显示/隐藏内容的vue过渡,如果顺利的话。虽然我理解css类和转换,但我可以使用不透明度或翻译等内容使内容显得“流畅”......但是一旦动画完成(或者更确切地说就是它开始),下面的任何html部分似乎都会“跳转” ”。
我正在尝试实现与Bootstrap 4'崩溃'类相同的效果 - 单击此处的顶部按钮之一:https://getbootstrap.com/docs/4.0/components/collapse/
当隐藏部分出现/消失时,所有html内容都会“滑动”。
使用v-if可以使用Vue转换来显示使用v-if显示的内容吗? vue过渡文档中的所有样本虽然具有很好的css过渡效果,但在过渡开始或完成后会有以下html'跳转'。
我见过一些使用max-height的纯js解决方案 - https://jsfiddle.net/wideboy32/7ap15qq0/134/
并试着用vue:https://jsfiddle.net/wideboy32/eywraw8t/303737/
.smooth-enter-active, .smooth-leave-active {
transition: max-height .5s;
}
.smooth-enter, .smooth-leave-to {
max-height: 0 .5s;
}
谢谢!
如果要为max-height设置动画,则应输入要设置动画的元素的最大高度量,并在最大高度定义中放置's'(或秒)时更正第二个类:
p{
max-height: 20px;
}
.smooth-enter-active, .smooth-leave-active {
transition: max-height .5s;
}
.smooth-enter, .smooth-leave-to {
max-height: 0;
}
如果你想要像bs4崩溃这样的东西那么vue网站里面的例子会做:
.smooth-enter-active, .smooth-leave-active {
transition: opacity .5s;
}
.smooth-enter, .smooth-leave-to {
opacity: 0
}
编辑:你想要做的是首先找出内容的高度,然后在.*-enter-to
和.*-leave
类中设置它。在下面的小提琴中演示了一种方法:
https://jsfiddle.net/rezaxdi/sxgyj1f4/3/
您也可以完全忘记v-if或v-show,只需使用高度值隐藏元素,我认为它更平滑:
我也有类似的任务。我发现没有JS就不可能做到这一点。所以我写自定义过渡组件(Reusable Transitions),它适用于我:
Vue.component('transition-collapse-height', {
template: `<transition
enter-active-class="enter-active"
leave-active-class="leave-active"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
>
<slot />
</transition>`,
methods: {
/**
* @param {HTMLElement} element
*/
beforeEnter(element) {
requestAnimationFrame(() => {
if (!element.style.height) {
element.style.height = '0px';
}
element.style.display = null;
});
},
/**
* @param {HTMLElement} element
*/
enter(element) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
element.style.height = `${element.scrollHeight}px`;
});
});
},
/**
* @param {HTMLElement} element
*/
afterEnter(element) {
element.style.height = null;
},
/**
* @param {HTMLElement} element
*/
beforeLeave(element) {
requestAnimationFrame(() => {
if (!element.style.height) {
element.style.height = `${element.offsetHeight}px`;
}
});
},
/**
* @param {HTMLElement} element
*/
leave(element) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
element.style.height = '0px';
});
});
},
/**
* @param {HTMLElement} element
*/
afterLeave(element) {
element.style.height = null;
},
},
});
new Vue({
el: '#app',
data: () => ({
isOpen: true,
}),
methods: {
onClick() {
this.isOpen = !this.isOpen;
}
}
});
.enter-active,
.leave-active {
overflow: hidden;
transition: height 1s linear;
}
.content {
background: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button @click="onClick">
open/hide
</button>
<transition-collapse-height>
<div v-show="isOpen" class="content">
<br/>
<br/>
<br/>
<br/>
</div>
</transition-collapse-height>
</div>