最近写了一个筛选功能,要使用手风琴效果展开内容,但是高度不固定,故此添加的动画效果失效,对此有两种解决方案
动画失效的原理是:
如果当前设置动画的元素他的父元素高度为auto的时候,且当前元素未设置position: absolute;属性,则transition无法生效
- 通常给需要展开/收起的元素(即添加了动画属性transition的元素),添加属性 position: absolute;就可以看到动画生效,但是脱离文档流之后,无法占据位置达不到想要的效果。
所以,最直接的办法是将height 替换成max-height ;例如:
height:40px; ⇒ max-height:40px;
height:100%; ⇒ max-height: 300px;
设置一个最大高度,主要是值不是很大一般不会出现卡顿,可以满足大部分需求
- 计算当前模块元素的高度,有时候计算高度很不方便,但是vue中可以使用一个简单的方法直接获取展开的高度
下面是两种实现方式的demo:
<template>
<div class="animate">
<p class="center-view">vue特效测试页面</p>
<div class="center-view">
<!-- 动态效果一-->
<div class="example">
<ul class="box">
<li v-for="(item,index) in 6" :key="index" @mouseenter="handerEnter($event,index)" @mouseleave="handerLeave($event,index)">
<div class="top" :class="[current == index ? 'evenClass' :'']"></div>
<div class="left" :class="[current == index ? 'oddClass' :'']"></div>
<div class="bottom" :class="[current == index ? 'evenClass' :'']"></div>
<div class="right" :class="[current == index ? 'oddClass' :'']"></div>
<img src="../../assets/images/openpic/2.png" alt="">
<p class="text" :class="[current == index ? 'showheight': '']">数字化能力</p>
</li>
</ul>
</div>
<!-- 动态效果二 -->
<div class="expand-example">
<div class="filters-box">
<div class="screening-conditions">
<div class="lable-content">
筛选条件:
</div>
<div class="tage-box">
<el-tag v-for="(tag,index) in Istags" :key="tag.name" @close="tagClose(tag,index)" closable :type="tag.type">
{{tag.name}}
</el-tag>
</div>
<div class="opertion">
<el-button @click="clearing">清空</el-button>
<span class="expandbtn" @click="openSelect">
展开筛选
<i class="el-icon-arrow-up" v-if="openflag"></i>
<i class="el-icon-arrow-down" v-else></i>
</span>
</div>
</div>
<!-- 筛选 -->
<div class="screen-array">
<div class="star-content" v-for="(item,index) in filterArray" :key="index">
<div class="lable-Name">
{{item.label}}:
</div>
<div class="tag-list first-List" :class="{isOpen:item.expand}">
<el-tag v-for="(tag,tagIndex) in item.list" :key="tag.name" @click="choose(tag,tagIndex)" closable :type="tag.type">
{{tag.name}}
</el-tag>
</div>
<div class="lookMore">
<span class="expandbtn" @click="MoreTags(item,index)">
{{item.expand ? "收起" : "展开"}}
<i class="el-icon-arrow-up" v-if="item.expand"></i>
<i class="el-icon-arrow-down" v-else></i>
</span>
</div>
</div>
</div>
</div>
</div>
<!-- js计算高度 -->
<div class="expand-example tow">
<div class="filters-box">
<div class="screening-conditions">
<div class="lable-content">
筛选条件:
</div>
<div class="tage-box">
<el-tag v-for="(tag,index) in Istags" :key="tag.name" @close="tagClose(tag,index)" closable :type="tag.type">
{{tag.name}}
</el-tag>
</div>
<div class="opertion">
<el-button @click="clearing">清空</el-button>
<span class="expandbtn" @click="openSelect">
展开筛选
<i class="el-icon-arrow-up" v-if="openflag"></i>
<i class="el-icon-arrow-down" v-else></i>
</span>
</div>
</div>
<!-- 筛选 -->
<div class="screen-array">
<div class="star-content" v-for="(item,index) in filterArrayTow" :key="index">
<div class="lable-Name">
{{item.label}}:
</div>
<div class="tag-list second-List" :style="{height:item.height}">
<div class="height_list" :ref="'listRef'+index">
<el-tag v-for="(tag,tagIndex) in item.list" :key="tag.name" @click="choose(tag,tagIndex)" closable :type="tag.type">
{{tag.name}}
</el-tag>
</div>
</div>
<div class="lookMore">
<span class="expandbtn" @click="setMore(item,index)">
{{item.expand ? "收起" : "展开"}}
<i class="el-icon-arrow-up" v-if="item.expand"></i>
<i class="el-icon-arrow-down" v-else></i>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
current: -1, // 当前的值
smallPic: [],
onePic: [
{
url: 'http://demo.datouwang.com/uploads/demo/jiaoben/2014/jiaoben321/img/small/car1-a.jpg'
},
{
url: 'http://demo.datouwang.com/uploads/demo/jiaoben/2014/jiaoben321/img/small/car1-b.jpg'
},
{
url: 'http://demo.datouwang.com/uploads/demo/jiaoben/2014/jiaoben321/img/small/car1-c.jpg'
},
],
towPic: [
{
url: 'http://demo.datouwang.com/uploads/demo/jiaoben/2014/jiaoben321/img/small/car3-a.jpg'
},
{
url: 'http://demo.datouwang.com/uploads/demo/jiaoben/2014/jiaoben321/img/small/car3-b.jpg'
},
],
flag: true,
openflag: false,// 选中的条件未展开
Istags: [
{ name: '标签一', type: '' },
{ name: '标签二', type: 'success' },
{ name: '标签三', type: 'info' },
{ name: '标签四', type: 'warning' },
{ name: '标签五', type: 'danger' }
],
filterArray: [
{
label: '所属部门',
expand: false, //是否展开
list: [
{ name: '全部', type: '' },
{ name: '橘右京', type: '' },
{ name: '露娜', type: '' },
{ name: '凯', type: '' },
{ name: '守约', type: '' },
{ name: '玄策', type: '' },
{ name: '木兰', type: '' },
{ name: '弈星', type: '' },
{ name: '不知火舞', type: '' },
{ name: '娜可露露', type: '' },
{ name: '昇', type: '' },
{ name: '牛牛公主', type: '' },
{ name: '狄仁杰', type: '' },
{ name: '鲁班七号', type: '' },
{ name: '蔡文姬', type: '' },
{ name: '李信', type: '' },
{ name: '阿离', type: '' },
]
},
{
label: '所属地区',
expand: false, //是否展开
list: [
{ name: '全部', type: '' },
{ name: '塔城', type: '' },
{ name: '塔克拉玛干', type: '' },
{ name: '吉林', type: '' },
{ name: '成都', type: '' },
{ name: '厦门', type: '' },
{ name: '上海', type: '' },
{ name: '丽江', type: '' },
{ name: '大理', type: '' },
{ name: '云南', type: '' },
{ name: '西藏', type: '' },
{ name: '四川', type: '' },
{ name: '兰州', type: '' },
{ name: '广州', type: '' },
{ name: '湖北', type: '' },
{ name: '甘肃', type: '' },
{ name: '山西', type: '' },
{ name: '陕西', type: '' },
{ name: '武汉', type: '' },
{ name: '浙江', type: '' },
]
},
],
filterArrayTow: [
{
label: '所属部门',
expand: false, //是否展开
height: '',
list: [
{ name: '全部', type: '' },
{ name: '橘右京', type: '' },
{ name: '露娜', type: '' },
{ name: '凯', type: '' },
{ name: '守约', type: '' },
{ name: '玄策', type: '' },
{ name: '木兰', type: '' },
{ name: '弈星', type: '' },
{ name: '不知火舞', type: '' },
{ name: '娜可露露', type: '' },
{ name: '昇', type: '' },
{ name: '牛牛公主', type: '' },
{ name: '狄仁杰', type: '' },
{ name: '鲁班七号', type: '' },
{ name: '蔡文姬', type: '' },
{ name: '李信', type: '' },
{ name: '阿离', type: '' },
]
},
{
label: '所属地区',
expand: false, //是否展开
height: '',
list: [
{ name: '全部', type: '' },
{ name: '塔城', type: '' },
{ name: '塔克拉玛干', type: '' },
{ name: '吉林', type: '' },
{ name: '成都', type: '' },
{ name: '厦门', type: '' },
{ name: '上海', type: '' },
{ name: '丽江', type: '' },
{ name: '大理', type: '' },
{ name: '云南', type: '' },
{ name: '西藏', type: '' },
{ name: '四川', type: '' },
{ name: '兰州', type: '' },
{ name: '广州', type: '' },
{ name: '湖北', type: '' },
{ name: '甘肃', type: '' },
{ name: '山西', type: '' },
{ name: '陕西', type: '' },
{ name: '武汉', type: '' },
{ name: '浙江', type: '' },
{ name: '景德镇', type: '' },
{ name: '库尔勒', type: '' },
{ name: '湖南', type: '' },
{ name: '长沙', type: '' },
{ name: '北京', type: '' },
{ name: '珠江', type: '' },
]
},
],
}
},
computed: {
styles() {
let length = 1
if (this.smallPic.length == 0) {
length = 1
} else {
length = this.smallPic.length + 2
}
if (length) {
let width = length * 120
let obj = {
width: width + 'px'
}
return obj
}
}
},
created() {
this.smallPic = this.onePic
},
mounted() { },
methods: {
handerEnter(event, index) {
// 鼠标移入
// console.log("EnterEvent",event,"index",index);
this.current = index
},
handerLeave(event, index) {
// 鼠标移出
this.current = -1
},
handlerNext() {
// 下一个系列
if (this.flag) {
this.smallPic = this.onePic
this.flag = false
} else {
this.smallPic = this.towPic
this.flag = true
}
},
clearing() {
},
openSelect() {
this.openflag = !this.openflag
},
tagClose(tag, index) {
console.log("关闭标签item", tag, "index", index);
},
choose(tag, index) {
console.log("选中标签item", tag, "index", index);
},
MoreTags(item, index) {
// console.log("查看更多item",item,"index",index);
this.filterArray[index].expand = !this.filterArray[index].expand
console.log("测试", this.filterArray[index].expand);
},
setMore(item, index) {
this.filterArrayTow[index].expand = !this.filterArrayTow[index].expand
let open = this.filterArrayTow[index].expand
console.log("~~~~",open,this.$refs['listRef'+index][0].offsetHeight);
if(open){
let height = this.$refs['listRef'+index][0].offsetHeight
console.log("div-->height",height,this.filterArrayTow[index].height);
this.filterArrayTow[index].height= height + 'px'
} else {
// 初始值
this.filterArrayTow[index].height = '45px'
}
// console.log("refs", this.$refs);
}
},
}
</script>
<style scoped lang="less">
.animate {
padding: 50px 0;
}
.center-view {
margin: 0 auto;
overflow: hidden;
width: 1200px;
background: #f5f8fc;
}
.example {
overflow: hidden;
}
.box {
li {
width: 380px;
height: 200px;
overflow: hidden;
margin: 10px;
float: left;
position: relative;
cursor: pointer;
background: #f6f6f6;
img {
width: 370px;
height: 190px;
position: absolute;
z-index: 1;
top: 5px;
left: 5px;
}
.top {
position: absolute;
top: 0;
width: 0px;
height: 5px;
z-index: 1;
transition: all ease-in 0.3s;
}
.bottom {
position: absolute;
z-index: 1;
width: 0%;
height: 5px;
bottom: 0;
right: 0;
transition: all ease-in 0.3s;
}
.right {
position: absolute;
z-index: 1;
width: 5px;
height: 0;
right: 0;
bottom: 0;
transition: all ease-in 0.3s;
}
.left {
position: absolute;
z-index: 1;
height: 0;
width: 5px;
left: 0;
// bottom: 0;
transition: all ease-in 0.3s;
}
.text {
position: absolute;
z-index: 2;
left: 5px;
bottom: 5px;
height: 0px;
width: 370px;
text-align: center;
color: #fff;
background: rgba(2, 179, 191, 0.5);
transition: all ease-in 0.3s;
line-height: 40px;
}
}
}
.showheight {
height: 40px !important;
}
.evenClass {
width: 100% !important;
// background: #02b3bf;
background: red;
}
.oddClass {
height: 100% !important;
// background: #02b3bf;
background: red;
}
.carbox {
background: #ddd;
width: 900px;
height: 450px;
padding: 10px;
margin: 0 auto;
position: relative;
margin-top: 80px;
box-sizing: content-box;
.big {
width: 900px;
height: 450px;
overflow: hidden;
img {
display: block;
width: 100%;
height: 100%;
}
}
.small {
width: 900px;
height: 140px;
overflow: hidden;
position: absolute;
bottom: 10px;
left: 10px;
.carousel {
float: left;
transition: width 0.3s ease;
img,
.next {
background: rgba(255, 255, 255, 0.2);
display: block;
width: 100px;
height: 100px;
padding: 10px;
margin: 0 0 20px 20px;
float: left;
box-sizing: content-box;
transition: background 0.6s ease;
}
img:hover,
.next:hover {
background: rgba(255, 255, 255, 0.3);
}
.next {
color: rgba(0, 0, 0, 0.5);
font-size: 120px;
line-height: 100px;
text-align: center;
text-decoration: none;
cursor: pointer;
}
}
.carousel:after {
content: '';
display: block;
clear: both;
}
}
}
.expand-example {
padding: 10px;
margin-top: 40px;
background: #efefef;
}
.filters-box {
background: #ffffff;
border-radius: 2px;
padding: 0 20px;
}
.screening-conditions {
display: flex;
justify-content: flex-start;
align-items: center;
height: 58px;
border-bottom: 2px solid #ebeef1;
.tage-box {
width: 80%;
padding: 0 20px;
.el-tag {
margin-right: 10px;
}
}
.expandbtn {
margin-left: 20px;
cursor: pointer;
}
}
.screen-array {
position: relative;
.star-content {
display: flex;
justify-content: space-between;
height: auto;
border-bottom: 1px solid #eee;
padding: 30px 0;
.tag-list {
padding: 0 20px;
flex: 1;
background: skyblue;
width: 86%;
.el-tag {
margin-right: 10px;
margin-bottom: 20px;
}
}
.first-List {
overflow: hidden;
max-height: 45px;
transition: max-height 1s;
}
.second-List {
background: pink;
height: 45px;
transition:height 1s;
overflow: hidden;
}
}
.lookMore {
width: 5%;
cursor: pointer;
}
}
.isOpen {
max-height: 200px !important;
}
</style>