Collapse 折叠面板源码:vue
<template> <!--一组折叠面板最外层包裹div--> <div class="el-collapse" role="tablist" aria-multiselectable="true"> <slot></slot> </div> </template> <script> export default { name: 'ElCollapse', componentName: 'ElCollapse', props: { accordion: Boolean, //是否手风琴模式 value: { //当前激活的面板(若是是手风琴模式,绑定值类型须要为string,不然为array) type: [Array, String, Number], default() { return []; } } }, data() { return { activeNames: [].concat(this.value) //当前激活的面板名称数组 }; }, provide() { return { collapse: this }; }, watch: { value(value) { this.activeNames = [].concat(value); } }, methods: { setActiveNames(activeNames) { // 返回activeNames数组的副本 activeNames = [].concat(activeNames); //若是是手风琴模式返回activeNames[0],不是则返回整个数组 let value = this.accordion ? activeNames[0] : activeNames; this.activeNames = activeNames; //触发父组件的input方法 this.$emit('input', value); //触发父组件的change方法 this.$emit('change', value); }, handleItemClick(item) { // 若是是手风琴模式 if (this.accordion) { this.setActiveNames( (this.activeNames[0] || this.activeNames[0] === 0) && this.activeNames[0] === item.name ? '' : item.name ); } else { //若是不是手风琴模式 let activeNames = this.activeNames.slice(0); let index = activeNames.indexOf(item.name); if (index > -1) { //若是该面板已是激活状态,就将其从activeNames数组中删除 activeNames.splice(index, 1); } else { //若是该面板还未是激活状态,就将其push进activeNames数组中 activeNames.push(item.name); } this.setActiveNames(activeNames); } } }, created() { this.$on('item-click', this.handleItemClick); } }; </script>
<template> <!--每一个折叠面板最外层包裹div--> <div class="el-collapse-item" :class="{'is-active': isActive}"> <div role="tab" :aria-expanded="isActive" :aria-controls="`el-collapse-content-${id}`" :aria-describedby ="`el-collapse-content-${id}`"> <!--面板头部,包含面板标题和箭头图标--> <div class="el-collapse-item__header" @click="handleHeaderClick" role="button" :id="`el-collapse-head-${id}`" tabindex="0" @keyup.space.enter.stop="handleEnterClick" :class="{ 'focusing': focusing, 'is-active': isActive }" @focus="handleFocus" @blur="focusing = false" > <!--折叠面板的标题--> <slot name="title">{{title}}</slot> <!--折叠面板的收起或折叠的箭头图标--> <i class="el-collapse-item__arrow el-icon-arrow-right" :class="{'is-active': isActive}"></i> </div> </div> <!--折叠面板内容区域 el-collapse-transition组件主要是为了添加内容显示隐藏时的动画效果--> <el-collapse-transition> <div class="el-collapse-item__wrap" v-show="isActive" role="tabpanel" :aria-hidden="!isActive" :aria-labelledby="`el-collapse-head-${id}`" :id="`el-collapse-content-${id}`" > <div class="el-collapse-item__content"> <slot></slot> </div> </div> </el-collapse-transition> </div> </template> <script> import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition'; import Emitter from 'element-ui/src/mixins/emitter'; import { generateId } from 'element-ui/src/utils/util'; export default { name: 'ElCollapseItem', componentName: 'ElCollapseItem', mixins: [Emitter], components: { ElCollapseTransition }, data() { return { contentWrapStyle: { height: 'auto', display: 'block' }, contentHeight: 0, focusing: false, isClick: false }; }, inject: ['collapse'], props: { title: String, name: { type: [String, Number], default() { return this._uid; } } }, computed: { // 返回当前面板是否被激活 isActive() { // 判断当前面板的名称是否在activeNames中 return this.collapse.activeNames.indexOf(this.name) > -1; }, id() { // 返回随机数id return generateId(); } }, methods: { handleFocus() { setTimeout(() => { if (!this.isClick) { this.focusing = true; } else { this.isClick = false; } }, 50); }, handleHeaderClick() { // 触发父组件的item-click事件 this.dispatch('ElCollapse', 'item-click', this); this.focusing = false; this.isClick = true; }, handleEnterClick() { this.dispatch('ElCollapse', 'item-click', this); } } }; </script>