作為一個有目標的人(目標是做一個好用的Bootstrap可視化編輯器,第一個版本已經實現,演示地址:https://vular.cn/rxeditor/,代碼地址:https://github.com/vularsoft/rxeditor),工作比較積極,思維也比較活躍,睡眠相對較少。今早6:30就 ...
作為一個有目標的人(目標是做一個好用的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上給我留言。