前端实现折叠、展开动画效果
1. 方案1: js + 动态class + transition
思路:
- 通过点击按钮切换状态值
- 根据不同状态值来切换不同的max-height、动态增删class,从而实现动画
优点:
实现简单、代码量少
缺点:
- max-height如果给小了,内容会展示不全;
- max-height如果给大了,折叠的动画效果就会不理想
- max-height 权重大!
代码示例:
<template>
<div>
<div id="article" class="article" :class="[status == 1 && 'extended']">
<p v-for="item in 30">我是内容自定义的一串文字.我是内容自定义的一串文字.</p>
</div>
<button id="seeMoreBtn" @click="openOrClose">{{btnTxt}}</button>
</div>
</template>
<script>
export default {
name: "index",
data() {
return {
status: 0, // 状态值
btnTxt: "查看更多" // 按钮文案
};
},
mounted() {},
methods: {
// 切换状态、按钮文案
openOrClose() {
this.status = this.status == 1 ? 0 : 1;
this.btnTxt = this.status == 1 ? "收起内容" : "查看更多";
}
}
};
</script>
<style lang='scss' scoped>
.article {
max-width: 800px;
max-height: 300px;
overflow-y: hidden;
/* 增加过渡时间以适应高度 */
transition: max-height 0.7s linear;
}
.extended {
max-height: 1000px !important;
}
button {
padding: 10px;
}
</style>
2. 方案2: transition-group + Velocity.js
优点:
交互体验好
缺点:
- 需要第三方插件支持
Velocity.js
- height 权重大!
代码示例:
<template>
<div class="container">
<div class="card">
<div id="hide-demo">
<transition-group
name="hide-fade"
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<p key="key1" v-if="status == 1" v-for="item in 30">我是内容自定义的一串文字.我是内容自定义的一串文字.</p>
<p key="key2" v-if="status == 0" v-for="item in 5">我是内容自定义的一串文字.我是内容自定义的一串文字.</p>
</transition-group>
<button @click="status = status == 1 ? 0 : 1">{{ status == 1 ? '收起说明':'其他说明'}}</button>
</div>
</div>
</div>
</template>
<script>
import Velocity from "/lib/velocity.min";
export default {
name: "index",
data() {
return {
status: 0
};
},
methods: {
beforeEnter: function(el) {
el.style.opacity = 0;
el.style.height = 0;
},
enter: function(el, done) {
console.log("enter");
const { status } = this;
setTimeout(function() {
Velocity(
el,
{ opacity: 1, height: status == 1 ? "50px" : "50px" },
{ complete: done }
);
}, 0);
},
leave: function(el, done) {
console.log("leave");
setTimeout(function() {
Velocity(el, { opacity: 0, height: 0 }, { complete: done });
}, 0);
}
}
};
</script>
<style lang='scss' scoped>
.container {
width: 400px;
}
.card {
border: 1px solid #ccc !important;
padding: 5px;
box-sizing: border-box;
}
</style>
注意:
transition-group
内部元素总是需要提供唯一的 key attribute 值, key 不能是 index