【Vue】vuejs如何实现这样的展开收起动画?
如图中的是jquery实现的,那么在vue中如何实现呢?
我试着用<transition>,但是用的很笨,望前辈们指教指教,如果能贴个示例代码的话,万分感谢~!
回答
这个组件当初自己也搞了很久,最后因为不知道隐藏层的高度没有使用css实现效果,可以参考element-ui通过overflow获取高度的方法创建了一个函数式组件实现了效果:
const elTransition = '0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out'const Transition = {
'before-enter' (el) {
el.style.transition = elTransition
if (!el.dataset) el.dataset = {}
el.dataset.oldPaddingTop = el.style.paddingTop
el.dataset.oldPaddingBottom = el.style.paddingBottom
el.style.height = 0
el.style.paddingTop = 0
el.style.paddingBottom = 0
},
'enter' (el) {
el.dataset.oldOverflow = el.style.overflow
if (el.scrollHeight !== 0) {
el.style.height = el.scrollHeight + 'px'
el.style.paddingTop = el.dataset.oldPaddingTop
el.style.paddingBottom = el.dataset.oldPaddingBottom
} else {
el.style.height = ''
el.style.paddingTop = el.dataset.oldPaddingTop
el.style.paddingBottom = el.dataset.oldPaddingBottom
}
el.style.overflow = 'hidden'
},
'after-enter' (el) {
el.style.transition = ''
el.style.height = ''
el.style.overflow = el.dataset.oldOverflow
},
'before-leave' (el) {
if (!el.dataset) el.dataset = {}
el.dataset.oldPaddingTop = el.style.paddingTop
el.dataset.oldPaddingBottom = el.style.paddingBottom
el.dataset.oldOverflow = el.style.overflow
el.style.height = el.scrollHeight + 'px'
el.style.overflow = 'hidden'
},
'leave' (el) {
if (el.scrollHeight !== 0) {
el.style.transition = elTransition
el.style.height = 0
el.style.paddingTop = 0
el.style.paddingBottom = 0
}
},
'after-leave' (el) {
el.style.transition = ''
el.style.height = ''
el.style.overflow = el.dataset.oldOverflow
el.style.paddingTop = el.dataset.oldPaddingTop
el.style.paddingBottom = el.dataset.oldPaddingBottom
}
}
export default {
name: 'collapseTransition',
functional: true,
render (h, { children }) {
const data = {
on: Transition
}
return h('transition', data, children)
}
}
然后就可以在需要的地方当做组件使用(不再需要css与其它逻辑):
<!-- 隐藏部分 -------------------------- -->
<collapse-transition>
<div class="collapse-wrap"
v-show="isActive">
<!-- @slot default -->
<slot></slot>
</div>
</collapse-transition>
给你个demo吧
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box{
height:500px;
background-color:black;
overflow: hidden;
}
.mybox-leave-active,.mybox-enter-active{
transition: all 1s ease;
}
.mybox-leave-active,.mybox-enter{
height:0px !important;
}
.mybox-leave,.mybox-enter-active{
height: 500px;
}
</style>
</head>
<body>
<div id="box">
<transition name="mybox">
<div class="box" v-show="boxshow"></div>
</transition>
<button @click="togglebox">按钮</button>
</div>
</body>
<script src="https://segmentfault.com/bower_components/vue/dist/vue.js"></script>
<script>
new Vue({
el:'#box',
data:{
boxshow:false
},
methods:{
togglebox:function(){
this.boxshow = !this.boxshow;
}
}
});
</script>
</html>
用动画试试看:
<transition name="router-slid"> //需要动画的内容
</transition>
css:
.router-slid-enter-active, .router-slid-leave-active { transition: all .4s;
}
.router-slid-enter, .router-slid-leave-active {
transform: translate3d(0, 3rem, 0);
opacity: 0;
}
补充一种情况: ul>li的情况,容器高度一般没有值(取决于元素的累加高度,或者其他情况),这种情况需要使用js的方式实现,height = 0 ,最终状态可以通过e.scrollHeight求到需要高度,这个属性很关键,宽度未知的情况也类似,参考crollHeight mdn
例子: https://codepen.io/huoguozhan...
可以参考这个,基本就是这样,你稍微调下样式就可以了
<template> <div class="panel">
<!-- body -->
<transition name="panel-fade"
@enter="enter"
@before-leave="beforeLeave"
@leave="leave"
>
<div class="panel__body" v-show="ifShowBody">
<slot></slot>
</div>
</transition>
<!-- footer -->
<div class="panel__footer" >
<slot name="header">更多</slot>
<i v-if="showIcon" class="panel__header__icon" :class="{[`arrow--${iconClass}`]: true}" @click="iconClick"></i>
</div>
</div>
</template>
<script>
import velocity from 'velocity-animate'
export default {
name: "ezy-panel",
props: {
showIcon: {
type: Boolean,
default: true
}
},
data() {
return {
iconClass: 'up',
bodyHeight: 0
}
},
computed: {
ifShowBody() {
var c = true;
switch (this.iconClass) {
case 'up':
c = true
break;
case 'down':
c = false
break;
}
return c
}
},
methods: {
iconClick() {
var self = this;
switch (this.iconClass) {
case 'up':
this.iconClass = 'down';
break;
case 'down':
this.iconClass = 'up';
break;
}
},
enter(el, done){
var self = this;
velocity(el, { height: self.bodyHeight + 'px' }, { duration: 500 , complete: done})
},
beforeLeave(el,done){
this.bodyHeight = el.clientHeight;
},
leave(el, done) {
el.style.height = el.clientHeight + 'px';
velocity(el, { height: '0px' }, { duration: 500 , complete: done})
}
}
}
用的时候,直接写主体部分可以,尾部的展开收缩,在组件里有了。
<panel>/* 直接写主体部分
* <div>...</div>
*/
</panel>
vue transition很容易的说。 用max-height效果最佳
in .vue: <transition name="sub-comments">
<div>...</div>
</transition>
in css:
.sub-comments-leave-active,.sub-comments-enter-active {
transition: max-height 0.3s;
}
.sub-comments-enter,.sub-comments-leave-to {
max-height:0 ;
}
.sub-comments-enter-to,.sub-comments-leave {
max-height: 4rem ;
}
上面的都能实现 ,其实大致思路都一样.附上另一种写法
vue部分<divclass="moreInfo" @click="boxshow = !boxshow">
展开
</div>
<div :class="boxshow==true?'box':'boxHidden' " ></div>
//boxshow默认为false
css部分
.box {
height:200px;
width: 100%;
background-color:black;
transition: all 0.5s ease-in-out;
}
.boxHidden{
transition: all 1s ease-in-out;
height: 0;
overflow: hidden;
}
变量控制状态:
外部控制height,overflow:hidden
内部控制一个transform:translateY
以上是 【Vue】vuejs如何实现这样的展开收起动画? 的全部内容, 来源链接: utcz.com/a/71862.html