作為一個有目标的人(目标是做一個好用的Bootstrap可視化編輯器,第一個版本已經實作,示範位址:https://vular.cn/rxeditor/,代碼位址:https://github.com/vularsoft/rxeditor),工作比較積極,思維也比較活躍,睡眠相對較少。今早6:30就起床了,吃早飯前,實作了一個手風琴式折疊元件,具體效果如下:
一般情況,這樣的控件有兩種表現形式:
1、排他展開,也就是一次隻有一個項目展開,其它閉合,類似QQ的好友分組。
2、随意展開,不拍它,可以同時展開多個
隻實作第二種方式,相對比較容易,每個子項目控制自己的狀态就可以,不用跟其它項目互動。我的目标式做一個控件,兩種方式都支援,通過屬性參數multiple确定是否可以同時展開多個。
添加新的檔案跟目錄:
跟上次實作Tabs控件一樣,有一個通用的子元件:CollapsibleItem,基于這個元件實作折疊元件:SimpleAccordion。如果以後像實作其它風格的折疊元件,可以共用CollapsibleItem元件。根據我個人的習慣,首先設想這個元件的使用方式,應該是這樣:<SimpleAccordion :multiple='true'>
<CollapsibleItem>
<template #heading>标題1</template>
<template #body>内容1....</template>
</CollapsibleItem>
<CollapsibleItem>
<template #heading>标題2</template>
<template #body>内容2....</template>
</CollapsibleItem>
</SimpleAccordion>
按照這樣的需求,先寫SimpleAccordion 的模闆代碼:
<template>
<div class="simple-accordion">
<slot></slot>
</div>
</template>
看起來非常簡單,接下來再寫CollapsibleItem的模闆代碼:
<template>
<div class="collapsible-item" :class="!isActive ? 'item-collapse' : ''">
<div class="item-heading" @click="click">
<slot name="heading"></slot>
</div>
<div class="item-body">
<slot name="body"></slot>
</div>
</div>
</template>
兩個slot分别對應每個折疊項的标題跟内容。如果該項被折疊的話,那麼放置css class: item-collapse。标題容器DIV接收click事件。腳本代碼:
export default {
name: 'CollapsibleItem',
props: {
selected: { default: false}
},
data() {
return {
isActive: false
};
},
methods: {
click() {
this.$emit('itemClick', this)
}
},
mounted() {
this.isActive = this.selected;
}
}
其他部分跟tabs控件一樣,并不難了解,需要注意的是click方法,這個方法接收到滑鼠點選事件後,在分發給它的父元件,本例中父元件就是SimpleAccordion。
再看SimpleAccordion的腳本代碼:
export default {
name: 'SimpleAccordion',
props: {
multiple: { default: false}
},
data() {
return {items: [] }
},
created() {
this.items = this.$children
},
mounted () {
this.items.forEach(item=>{
item.$on('itemClick', this.itemClick)
})
},
methods: {
itemClick(clickedItem) {
clickedItem.isActive = !clickedItem.isActive
if(!this.multiple){
this.items.forEach(item => {
if(item !== clickedItem){
item.isActive = false
}
})
}
}
}
}
在mounted的方法中,在所有的子項上注冊事件“itemClick”,這個事件在子元件中分發。事件處理方法itemClick根據需要,激活相應的項目。
這樣這個控件就完成了,對應的CSS:
.simple-accordion{
flex: 1;
width: 100%;
overflow: auto;
height: 0;
display: flex;
flex-flow: column;
margin-top: 2px;
}
.simple-accordion .collapsible-item{
display: flex;
flex-flow: column;
width: 100%;
}
.simple-accordion .item-heading{
display: flex;
flex-flow: row;
flex-wrap: wrap;
align-items: center;
font-size: 12px;
color:#f0f1ef;
padding-left: 10px;
padding-top:10px;
padding-bottom:10px;
padding-right:20px;
position: relative;
border-top:#484848 solid 1px;
border-bottom:#282828 solid 1px;
cursor: default;
}
.simple-accordion .item-heading:hover{
background: #383838;
}
.simple-accordion .collapsible-item .item-heading span{
margin-right: 5px;
}
.simple-accordion .collapsible-item .item-heading small{
white-space:nowrap;
color: #aaa;
font-size: 11px;
}
.simple-accordion .collapsible-item .item-heading::after{
position: absolute;
content: '';
width: 0;
height: 0;
top: calc(50% -1px);
right: 19px;
border-width: 4px;
border-style: solid;
border-color: #f0f1ef transparent transparent transparent;
}
.simple-accordion .item-body{
border-top:#282828 solid 1px;
padding: 10px;
}
.simple-accordion .collapsible-item.item-collapse .item-heading::after{
position: absolute;
content: '';
width: 0;
height: 0;
top: calc(50% -1px);
right: 17px;
border-width: 4px;
border-style: solid;
border-color:transparent transparent transparent #f0f1ef;
}
.simple-accordion .collapsible-item.item-collapse .item-body{
display: none;
}
.simple-accordion .item-body .element{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: move;
color: #c2c2c2;
font-size: 13px;
padding:5px 5px;
margin:3px;
display: flex;
flex-flow: row;
justify-content: space-between;
align-items: center;
}
.simple-accordion .item-body .element:hover{
color: #75b325;
box-shadow: 2px 2px 5px 0px rgba(0, 0, 0, 0.4);
}
View Code
做這個控件時,碰到了一些細小問題,調整了項目的CSS,其中比較重要的有以下幾點:
1、視窗拖動時,拖動把手會被擠沒,在把手的CCS中添加:
flex-shrink: 0;
這樣可以避免handle被擠小擠沒
2、SimpleAccordion寬度設為100%,他會把父元件WidgetTabs撐大,失去拖放效果。後來追蹤到是WidgetTabs的父元素沒有設定寬度,從widgettabs到固定寬度的父容器,全部設定寬度100%:
.left-inner{
width:100%;
}
.top-area{
width:100%;
}
3、用于顯示展開閉合的箭頭,使用css繪制,具體繪制原理,請自行百度。
整個項目在這個曆史節點的代碼,請到我的Github上檢視:https://github.com/vularsoft/studio-ui
找到該曆史節點的方法:
RXEditor是一個Boostrap代碼可視化編輯工具,本系列記錄了該軟體的開發過程,有問題的朋友請在ithub上給我留言。