Files
2025-04-30 14:04:34 +08:00

190 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="benben-collapse-item">
<view @click="onClick(!isOpen)" :class="{ open: isheight }">
<slot name="title" v-bind:isOpen="isOpen" v-bind:disabled="disabled"></slot>
<slot name="line" v-if="border"></slot>
</view>
<view class="benben-collapse-item__wrap" :class="{ 'is--transition': showAnimation }">
<view :id="elId" ref="collapse--hook" class="benben-collapse-item__wrap-content">
<slot v-if="isOpen" name="content"></slot>
</view>
</view>
</view>
</template>
<script>
/**
* CollapseItem 折叠面板子组件
* @description 折叠面板子组件
* @property {String} title 标题文字
* @property {String} thumb 标题左侧缩略图
* @property {String} name 唯一标志符
* @property {Boolean} open = [true|false] 是否展开组件
* @property {Boolean} border = [true|false] 是否显示分隔线
* @property {Boolean} disabled = [true|false] 是否展开面板
* @property {Boolean} showAnimation = [true|false] 开启动画
*/
export default {
name: 'benben-collapse-item',
props: {
// 列表标题
title: {
type: String,
default: '',
},
name: {
type: [Number, String],
default: '',
},
// 是否禁用
disabled: {
type: Boolean,
default: false,
},
// #ifdef APP-PLUS
// 是否显示动画,app 端默认不开启动画,卡顿严重
showAnimation: {
type: Boolean,
default: false,
},
// #endif
// #ifndef APP-PLUS
// 是否显示动画
showAnimation: {
type: Boolean,
default: true,
},
// #endif
// 是否展开
open: {
type: Boolean,
default: false,
},
// 缩略图
thumb: {
type: String,
default: '',
},
// 是否显示边框
border: {
type: Boolean,
default: false,
},
},
data() {
// TODO 随机生生元素ID解决百度小程序获取同一个元素位置信息的bug
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
return {
isOpen: false,
isheight: null,
height: 0,
elId,
nameSync: 0,
}
},
watch: {
open(val) {
this.isOpen = val
this.onClick(val, 'init')
},
},
updated(e) {
this.$nextTick(() => {
this.init(true)
})
},
created() {
this.collapse = this.getCollapse()
this.onClick(this.open, 'init')
},
mounted() {
if (!this.collapse) return
if (this.name !== '') {
this.nameSync = this.name
} else {
this.nameSync = this.collapse.childrens.length + ''
}
if (this.collapse.names.indexOf(this.nameSync) === -1) {
this.collapse.names.push(this.nameSync)
} else {
console.warn(`name 值 ${this.nameSync} 重复`)
}
if (this.collapse.childrens.indexOf(this) === -1) {
this.collapse.childrens.push(this)
}
this.init()
},
methods: {
init(type) {
// #ifndef APP-NVUE
this.getCollapseHeight(type)
// #endif
},
onClick(isOpen, type) {
if (this.disabled) return
this.isOpen = isOpen
if (this.isOpen && this.collapse) {
this.collapse.setAccordion(this)
}
if (type !== 'init') {
this.collapse.onChange(isOpen, this)
}
},
getCollapseHeight(type, index = 0) {
const views = uni.createSelectorQuery().in(this)
views
.select(`#${this.elId}`)
.fields(
{
size: true,
},
(data) => {
// TODO 百度中可能获取不到节点信息 ,需要循环获取
if (index >= 10) return
if (!data) {
index++
this.getCollapseHeight(false, index)
return
}
// #ifndef APP-NVUE
this.height = data.height
// #endif
this.isheight = true
if (type) return
this.onClick(this.isOpen, 'init')
}
)
.exec()
},
/**
* 获取父元素实例
*/
getCollapse(name = 'benben-flex-collapse') {
let parent = this.$parent
let parentName = parent.$options.name
while (parentName !== name) {
parent = parent.$parent
if (!parent) return false
parentName = parent.$options.name
}
return parent
},
},
}
</script>
<style lang="scss">
.benben-collapse-item {
}
.benben-collapse-item__wrap {
overflow: hidden;
}
.is--transition {
// transition: all 0.3s;
transition-property: height, border-bottom-width;
transition-duration: 0.3s;
/* #ifndef APP-NVUE */
will-change: height;
/* #endif */
}
</style>