作为一个有目标的人(目标是做一个好用的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:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
.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); }
做这个控件时,碰到了一些细小问题,调整了项目的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上给我留言。