【Vue】vuejs如何实现这样的展开收起动画?

【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

回到顶部