出发点
虽然 Element 也有 el-collapse 组件,但是当我只想写一个折叠面板时,它的写法就略显繁琐了,el-card 组件的样式也更符合我的需求,所以我就想着给 el-card 添加折叠功能。
1 效果
在线演示:https://lruihao.github.io/vue-el-demo/#/card-collapse
2 实现过程
一开始想着使用 Vue 的自定义指令功能来实现,但是动手之前还是习惯性地先看 el-card 的源码,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <template> <div class="el-card" :class="shadow ? 'is-' shadow '-shadow' : 'is-always-shadow'"> <div class="el-card__header" v-if="$slots.header || header"> <slot name="header">{{ header }}</slot> </div> <div class="el-card__body" :style="bodyStyle"> <slot></slot> </div> </div> </template> <script> export default { name: 'ElCard', props: { header: {}, bodyStyle: {}, shadow: { type: String } } }; </script> |
---|
这一看源码这么简单,直接改得了,还用啥自定义指令,开干!
3 实现方式
- 通过继承 el-card 组件来实现,这样就不用改 el-card 的源码了,也不用担心升级 Element 时会被覆盖掉。
- 然后在继承的组件中添加一个
isCollapse
属性来控制折叠状态。
继承也很简单,这样简单几行就完整继承了原来 el-card 的所有功能了:
1 2 3 4 5 6 7 | <script> import { Card } from 'element-ui' export default { name: 'ElCardCollapse', extends: Card, } </script> |
---|
然后,把 el-card template 中的代码先原封不动地复制过来,再在需要的地方添加折叠按钮和相关逻辑就行了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <template> <div class="el-card" :class="shadow ? 'is-' shadow '-shadow' : 'is-always-shadow'"> <div v-if="$slots.header || header" class="el-card__header" :class="isCollapseSelf ? 'collapse-icon-right' : 'collapse-icon-down'" @click="isCollapseSelf = !isCollapseSelf" > <slot name="header">{{ header }}</slot> </div> <div class="el-card__body" :style="bodyStyle" :class="{'is-collapse': isCollapseSelf}" > <slot /> </div> </div> </template> <script> import { Card } from 'element-ui' export default { name: 'ElCardCollapse', extends: Card, props: { isCollapse: { type: Boolean, default: false, }, }, data() { return { isCollapseSelf: this.isCollapse, } }, } </script> <style lang="scss" scoped> .el-card__header { cursor: pointer; position: relative; &::after { font-family: element-icons !important; speak: none; font-style: normal; font-weight: 400; font-variant: normal; text-transform: none; line-height: 1; vertical-align: baseline; display: inline-block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); } &.collapse-icon-right::after { content: 'e6e0'; } &.collapse-icon-down::after { content: 'e6df'; } } .is-collapse { display: none; } </style> |
---|
4 使用方法
在 main.js
中引入:
1 2 | import ElCardCollapse from '@/components/ElCardCollapse.vue' Vue.component('ElCardCollapse', ElCardCollapse) |
---|
写法和 el-card 一样,只是多了一个 is-collapse
属性,使用 el-card-collapse
代替 el-card
即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <template> <div> <el-card-collapse class="box-card" :is-collapse="isCollapse"> <div slot="header" class="flex-between"> <span>卡片名称</span> <el-button style="padding: 3px 0; margin-right: 10px;" type="text">操作按钮</el-button> </div> <div v-for="o in 4" :key="o" class="text item"> {{ '列表内容 ' o }} </div> </el-card-collapse> </div> </template> <script> export default { name: 'CardCollapse', data() { return { isCollapse: true, } }, } </script> <style lang="scss" scoped> .text { font-size: 14px; } .item { margin-bottom: 18px; } .flex-between { display: flex; justify-content: space-between; align-items: center; } .box-card { width: 480px; } </style> |
---|