美文网首页
VUE 实现 Studio 管理后台(五):手风琴式折叠组件(A

VUE 实现 Studio 管理后台(五):手风琴式折叠组件(A

作者: 悠闲的水 | 来源:发表于2020-03-06 11:14 被阅读0次

    作为一个有目标的人(目标是做一个好用的 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);

      }

    做这个控件时,碰到了一些细小问题,调整了项目的 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

    相关文章

      网友评论

          本文标题:VUE 实现 Studio 管理后台(五):手风琴式折叠组件(A

          本文链接:https://www.haomeiwen.com/subject/dxgvrhtx.html