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>