Collapse 摺疊面板源碼: collapse.vue collapse item.vue ...
Collapse 摺疊面板源碼:
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>
collapse-item.vue
<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>