237 lines
5.6 KiB
Vue
237 lines
5.6 KiB
Vue
<template>
|
||
<view class="tn-collapse-item-class tn-collapse-item" :style="[itemStyle]">
|
||
<!-- 头部 -->
|
||
<view
|
||
class="tn-collapse-item__head"
|
||
:style="[headStyle]"
|
||
:hover-stay-time="200"
|
||
:hover-class="hoverClass"
|
||
@tap.stop="headClick"
|
||
>
|
||
<block v-if="!$slots['title-all'] || !$slots['$title-all']">
|
||
<view
|
||
v-if="!$slots.title || !$slots.$title"
|
||
class="tn-collapse-item__head__title tn-text-ellipsis"
|
||
:style="[
|
||
{ textAlign: align ? align : 'left'},
|
||
isShow && activeStyle && !arrow ? activeStyle : ''
|
||
]"
|
||
>{{ title }}</view>
|
||
<view v-else>
|
||
<slot name="title"></slot>
|
||
</view>
|
||
<view class="tn-collapse-item__head__icon__wrap">
|
||
<view
|
||
v-if="arrow"
|
||
class="tn-icon-down tn-collapse-item__head__icon__arrow"
|
||
:class="{'tn-collapse-item__head__icon__arrow--active': isShow}"
|
||
:style="[arrowIconStyle]"
|
||
></view>
|
||
</view>
|
||
</block>
|
||
<view v-else>
|
||
<slot name="title-all"></slot>
|
||
</view>
|
||
</view>
|
||
<!-- 内容 -->
|
||
<view
|
||
class="tn-collapse-item__body"
|
||
:style="[{
|
||
height: isShow ? height + 'px' : '0'
|
||
}]"
|
||
>
|
||
<view class="tn-collapse-item__body__content" :id="elId" :style="[bodyStyle]">
|
||
<slot></slot>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'tn-collapse-item',
|
||
props: {
|
||
// 展开
|
||
open: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 唯一标识
|
||
name: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 标题
|
||
title: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 标题对齐方式
|
||
align: {
|
||
type: String,
|
||
default: 'left'
|
||
},
|
||
// 点击不收起
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 活动时样式
|
||
activeStyle: {
|
||
type: Object,
|
||
default() {
|
||
return {}
|
||
}
|
||
},
|
||
// 标识
|
||
index: {
|
||
type: [Number, String],
|
||
default: ''
|
||
}
|
||
},
|
||
computed: {
|
||
arrowIconStyle() {
|
||
let style = {}
|
||
if (this.arrowColor) {
|
||
style.color = this.arrowColor
|
||
}
|
||
return style
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
isShow: false,
|
||
elId: this.$tn.uuid(),
|
||
// body高度
|
||
height: 0,
|
||
// 头部样式
|
||
headStyle: {},
|
||
// 主体样式
|
||
bodyStyle: {},
|
||
// item样式
|
||
itemStyle: {},
|
||
// 显示右边箭头
|
||
arrow: true,
|
||
// 箭头颜色
|
||
arrowColor: '',
|
||
// 点击头部时的效果样式
|
||
hoverClass: ''
|
||
}
|
||
},
|
||
watch: {
|
||
open(value) {
|
||
this.isShow = value
|
||
}
|
||
},
|
||
created() {
|
||
this.parent = false
|
||
this.isShow = this.open
|
||
},
|
||
mounted() {
|
||
this.init()
|
||
},
|
||
methods: {
|
||
// 异步获取内容或者修改了内容时重新获取内容的信息
|
||
init() {
|
||
this.parent = this.$tn.$parent.call(this, 'tn-collapse')
|
||
if (this.parent) {
|
||
this.nameSync = this.name ? this.name : this.parent.childrens.length
|
||
// 不存在才添加对应实例
|
||
!this.parent.childrens.includes(this) && this.parent.childrens.push(this)
|
||
this.headStyle = this.parent.headStyle
|
||
this.bodyStyle = this.parent.bodyStyle
|
||
this.itemStyle = this.parent.itemStyle
|
||
this.arrow = this.parent.arrow
|
||
this.arrowColor = this.parent.arrowColor
|
||
this.hoverClass = this.parent.hoverClass
|
||
}
|
||
this.$nextTick(() => {
|
||
this.queryRect()
|
||
})
|
||
},
|
||
// 点击头部
|
||
headClick() {
|
||
if (this.disabled) return
|
||
if (this.parent && this.parent.accordion) {
|
||
this.parent.childrens.map(child => {
|
||
// 如果是手风琴模式,将其他的item关闭
|
||
if (this !== child) {
|
||
child.isShow = false
|
||
}
|
||
})
|
||
}
|
||
|
||
this.isShow = !this.isShow
|
||
// 触发修改事件
|
||
this.$emit('change', {
|
||
index: this.index,
|
||
show: this.isShow
|
||
})
|
||
// 只有在打开时才触发父元素的change
|
||
if (this.isShow) this.parent && this.parent.onChange()
|
||
this.$forceUpdate()
|
||
},
|
||
// 查询内容高度
|
||
queryRect() {
|
||
this._tGetRect('#'+this.elId).then(res => {
|
||
this.height = res.height
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
|
||
.tn-collapse-item {
|
||
|
||
&__head {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
color: $tn-font-color;
|
||
font-size: 30rpx;
|
||
line-height: 1;
|
||
padding: 24rpx 0;
|
||
padding-left: 24rpx;
|
||
text-align: left;
|
||
background-color: #FFFFFF;
|
||
|
||
&__title {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
}
|
||
|
||
&__icon {
|
||
&__arrow {
|
||
transition: all 0.3s;
|
||
margin-right: 20rpx;
|
||
margin-left: 14rpx;
|
||
font-size: inherit;
|
||
|
||
&--active {
|
||
transform: rotate(180deg);
|
||
transform-origin: center center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
&__body {
|
||
transition: all 0.3s;
|
||
overflow: hidden;
|
||
|
||
&__content {
|
||
overflow: hidden;
|
||
font-size: 28rpx;
|
||
color: $tn-font-color;
|
||
text-align: left;
|
||
background-color: #FFFFFF;
|
||
padding-left: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
</style>
|