简易折叠面板

本文介绍了一个使用Vue.js实现的折叠面板组件,包括主文件app.vue的结构与样式定义,以及两个子组件Collpase和CollpaseItem的功能实现细节。组件支持动画效果、禁用状态及单选模式。

在这里插入图片描述
代码如下:

主文件:app.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <collpase>
      <collpase-item
        :title="item.name"
        :showAnimation="true"
        v-for="(item, i) in chapterList"
        :key="i"
      >
        <div class="list" v-for="(it, index) in item.list" :key="index">
          {{it.name}}
        </div>
      </collpase-item>
    </collpase>
  </div>
</template>

<script>
import Collpase from './components/Collpase.vue';
import CollpaseItem from './components/CollpaseItem.vue'

export default {
  name: 'App',
  data() {
    return {
      chapterList: [
        {
          name: '标题一',
          list: [
            {
              name: '是是是是是是所'
            },
            {
              name: '啊啊啊啊'
            }
          ]
        },
        {
          name: '标题二',
          list: [
            {
              name: '是是是是是是所'
            },
            {
              name: '啊啊啊啊'
            },
            {
              name: '啊啊啊啊'
            }
          ]
        }
      ]
    }
  },
  components: {
    Collpase,
    CollpaseItem,
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

子组件:

<template>
	<div class="collapse">
		<slot />
	</div>
</template>
<script>
	export default {
		name: 'Collapse',
		props: {
			accordion: {
				type: [Boolean, String],
				default: false
			}
		},
		provide() {
			return {
				collapse: this
			}
		},
		created() {
			this.childrens = []
		},
		methods: {
			onChange() {
				let activeItem = []
				this.childrens.forEach((vm) => {
					if (vm.isOpen) {
						activeItem.push(vm.nameSync)
					}
				})
				this.$emit('change', activeItem)
			}
		}
	}
</script>
<style lang="css" scoped>
	.collapse {
		width: 100%;
		display: flex;
		flex: 1;
		flex-direction: column;
	}
</style>

子组件:

<template>
	<div>
    <div :class="{ 'collapse-disabled': disabled,'collapse-cell--notdisabled': !disabled, 'collapse-cell--open': isOpen,'collapse-cell--hide':!isOpen }" class="collapse-cell">
      <div :class="{ 'collapse-disabled': disabled}" class="collapse-cell__title"  @click="onClick">
        <span class="collapse-cell__title-text">{{ title }}</span>
        <img :class="{ 'active': isOpen, 'active-animation': showAnimation === true }" class="title-arrow" src="https://static-mumway.oss-cn-zhangjiakou.aliyuncs.com/NetworkFrontEnd/wsj/yslbq/btn_dropdown.png"/>
      </div>
      <div :class="{'collapse-cell__content--hide':!isOpen}" class="collapse-cell__content">
        <div :class="{ 'active-animation': showAnimation === true }" class="collapse-cell__wrapper" :style="{'transform':isOpen?'translateY(0)':'translateY(-50%)','-webkit-transform':isOpen?'translateY(0)':'translateY(-50%)'}">
          <slot />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
	export default {
		name: 'UniCollapseItem',
		props: {
			title: {
				// 列表标题
				type: String,
				default: ''
			},
			name: {
				// 唯一标识符
				type: [Number, String],
				default: 0
			},
			disabled: {
				// 是否禁用
				type: Boolean,
				default: false
			},
			showAnimation: {
				// 是否显示动画
				type: Boolean,
				default: false
			},
			open: {
				// 是否展开
				type: Boolean,
				default: false
			},
			thumb: {
				// 缩略图
				type: String,
				default: ''
			}
		},
		data() {
			return {
				isOpen: false
			}
		},
		watch: {
			open(val) {
				this.isOpen = val
			}
		},
		inject: ['collapse'],
		created() {
			this.isOpen = this.open
			this.nameSync = this.name ? this.name : this.collapse.childrens.length
			this.collapse.childrens.push(this)
			if (String(this.collapse.accordion) === 'true') {
				if (this.isOpen) {
					let lastEl = this.collapse.childrens[this.collapse.childrens.length - 2]
					if (lastEl) {
						this.collapse.childrens[this.collapse.childrens.length - 2].isOpen = false
					}
				}
			}
		},
		methods: {
			onClick() {
				if (this.disabled) {
					return
				}
				if (String(this.collapse.accordion) === 'true') {
					this.collapse.childrens.forEach(vm => {
						if (vm === this) {
							return
						}
						vm.isOpen = false
					})
				}
				this.isOpen = !this.isOpen
				this.collapse.onChange && this.collapse.onChange()
				this.$forceUpdate()
			}
		}
	}
</script>

<style lang="css" scoped>
	.collapse-cell {
		flex-direction: column;
		border-color: #f0f0f0;
		border-bottom-width: 1px;
	}
	.collapse-cell--open {
		background-color: #fff;
	}
	.collapse-disabled {
		cursor: not-allowed !important;
	}
	.collapse-cell--hide {
		height: 48px;
	}
	.active-animation {
		transition-property: transform;
		transition-duration: 0.3s;
		transition-timing-function: ease;
	}

	.collapse-cell__title {
		border-bottom: 1px solid #f0f0f0;
		padding: 12px 20px;
		position: relative;
		display: flex;
		width: 100%;
		box-sizing: border-box;
		height: 44px;
		line-height: 44px;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
		cursor: pointer;
	}
	.collapse-cell__title-img {
		margin-right: 10px;
	}
	.title-arrow {
		width: 22px;
		height: 14px;
	}
	.active {
		transform: rotate(180deg);
	}
	.collapse-cell__title-text {
		flex: 1;
		font-size: 16px;
		margin-right: 16px;
		white-space: nowrap;
		color: #333333;
    font-weight: bold;
		lines: 1;
		overflow: hidden;
		text-overflow: ellipsis;
	}
	.collapse-cell__content {
		overflow-x: hidden;
	}
	.collapse-cell__wrapper {
		display: flex;
		flex-direction: column;
	}
	.collapse-cell__content--hide {
		height: 0px;
		line-height: 0px;
	}
</style>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值