Skip to content

Commit 11209b0

Browse files
committed
增加可拖动抽屉组件drag-drawer
1 parent e78f77f commit 11209b0

File tree

11 files changed

+375
-3
lines changed

11 files changed

+375
-3
lines changed

Diff for: src/components/drag-drawer/drag-drawer-trigger.vue

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<div :class="`${prefix}-move-trigger`">
3+
<div :class="`${prefix}-move-trigger-point`">
4+
<i></i><i></i><i></i><i></i><i></i>
5+
</div>
6+
</div>
7+
</template>
8+
9+
<script>
10+
import Mixin from './mixin'
11+
export default {
12+
name: 'DragDrawerTrigger',
13+
mixins: [Mixin]
14+
}
15+
</script>
16+
17+
<style>
18+
</style>

Diff for: src/components/drag-drawer/drag-drawer.vue

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<template>
2+
<Drawer ref="drawerWrapper"
3+
:value="value"
4+
@input="handleInput"
5+
:width="width"
6+
:class-name="outerClasses"
7+
v-bind="$attrs"
8+
v-on="$listeners">
9+
<!-- 所有插槽内容显示在这里 ↓ -->
10+
11+
<template v-for="(slots, slotsName) in $slots">
12+
<template v-if="slotsName !== 'default'">
13+
<render-dom v-for="(render, index) in slots"
14+
:key="`b_drawer_${slotsName}_${index}`"
15+
:render="() => render"
16+
:slot="slotsName">
17+
</render-dom>
18+
</template>
19+
<template v-else>
20+
<div :class="`${prefix}-body-wrapper`"
21+
:key="`b_drawer_${slotsName}`">
22+
<render-dom v-for="(render, index) in slots"
23+
:key="`b_drawer_${slotsName}_${index}`"
24+
:render="() => render"
25+
:slot="slotsName">
26+
</render-dom>
27+
</div>
28+
</template>
29+
</template>
30+
<!-- 所有插槽内容显示在这里 ↑ -->
31+
<div v-if="draggable"
32+
:style="triggerStyle"
33+
:class="`${prefix}-trigger-wrapper`"
34+
@mousedown="handleTriggerMousedown">
35+
<slot name="trigger">
36+
<drag-drawer-trigger></drag-drawer-trigger>
37+
</slot>
38+
</div>
39+
<div v-if="$slots.footer"
40+
:class="`${prefix}-footer`">
41+
<slot name="footer"></slot>
42+
</div>
43+
</Drawer>
44+
</template>
45+
46+
<script>
47+
import RenderDom from '@/libs/render-dom'
48+
import DragDrawerTrigger from './drag-drawer-trigger.vue'
49+
import Mixin from './mixin'
50+
import { on, off } from '@/libs/tools'
51+
import './index.less'
52+
export default {
53+
name: 'BDrawer',
54+
components: {
55+
RenderDom,
56+
DragDrawerTrigger
57+
},
58+
mixins: [Mixin],
59+
props: {
60+
value: {
61+
type: Boolean,
62+
default: false
63+
},
64+
width: {
65+
type: [String, Number],
66+
default: 256
67+
},
68+
// 是否可拖动修改宽度
69+
draggable: {
70+
type: Boolean,
71+
default: false
72+
},
73+
// 最小拖动宽度
74+
minWidth: {
75+
type: [String, Number],
76+
default: 256
77+
}
78+
},
79+
data () {
80+
return {
81+
canMove: false,
82+
wrapperWidth: 0,
83+
wrapperLeft: 0
84+
}
85+
},
86+
computed: {
87+
outerClasses () {
88+
const classesArray = [
89+
`${this.prefix}-wrapper`,
90+
this.canMove ? 'no-select pointer-events-none' : ''
91+
]
92+
return classesArray.join(' ')
93+
},
94+
placement () {
95+
return this.$attrs.placement
96+
},
97+
innerWidth () {
98+
const width = this.width
99+
return width <= 100 ? (this.wrapperWidth * width) / 100 : width
100+
},
101+
triggerStyle () {
102+
return {
103+
[this.placement]: `${this.innerWidth}px`,
104+
position: this.$attrs.inner ? 'absolute' : 'fixed'
105+
}
106+
}
107+
},
108+
methods: {
109+
handleInput (status) {
110+
this.$emit('input', status)
111+
},
112+
handleTriggerMousedown (event) {
113+
this.canMove = true
114+
this.$emit('on-resize-start')
115+
// 防止鼠标选中抽屉中文字,造成拖动trigger触发浏览器原生拖动行为
116+
window.getSelection().removeAllRanges()
117+
},
118+
handleMousemove (event) {
119+
if (!this.canMove) return
120+
// 更新容器宽度和距离左侧页面距离,如果是window则距左侧距离为0
121+
this.setWrapperWidth()
122+
const left = event.pageX - this.wrapperLeft
123+
// 如果抽屉方向为右边,宽度计算需用容器宽度减去left
124+
let width = this.placement === 'right' ? this.wrapperWidth - left : left
125+
// 限定做小宽度
126+
width = Math.max(width, parseFloat(this.minWidth))
127+
event.atMin = width === parseFloat(this.minWidth)
128+
// 如果当前width不大于100,视为百分比
129+
if (width <= 100) width = (width / this.wrapperWidth) * 100
130+
this.$emit('update:width', parseInt(width))
131+
this.$emit('on-resize', event)
132+
},
133+
handleMouseup (event) {
134+
this.canMove = false
135+
this.$emit('on-resize-end')
136+
},
137+
setWrapperWidth () {
138+
const {
139+
width,
140+
left
141+
} = this.$refs.drawerWrapper.$el.getBoundingClientRect()
142+
this.wrapperWidth = width
143+
this.wrapperLeft = left
144+
}
145+
},
146+
mounted () {
147+
on(document, 'mousemove', this.handleMousemove)
148+
on(document, 'mouseup', this.handleMouseup)
149+
this.setWrapperWidth()
150+
},
151+
beforeDestroy () {
152+
off(document, 'mousemove', this.handleMousemove)
153+
off(document, 'mouseup', this.handleMouseup)
154+
}
155+
}
156+
</script>

Diff for: src/components/drag-drawer/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import DragDrawer from './drag-drawer.vue'
2+
export default DragDrawer

Diff for: src/components/drag-drawer/index.less

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
@prefix: ~"drag-drawer";
2+
@drag-drawer-trigger-height: 100px;
3+
@drag-drawer-trigger-width: 8px;
4+
5+
.@{prefix}-wrapper{
6+
&.no-select{
7+
user-select: none;
8+
}
9+
&.pointer-events-none{
10+
pointer-events: none;
11+
& .@{prefix}-trigger-wrapper{
12+
pointer-events: all;
13+
}
14+
}
15+
.ivu-drawer{
16+
&-header{
17+
overflow: hidden !important;
18+
box-sizing: border-box;
19+
}
20+
&-body{
21+
padding: 0;
22+
overflow: visible;
23+
position: static;
24+
display: flex;
25+
flex-direction: column;
26+
}
27+
}
28+
.@{prefix}-body-wrapper{
29+
width: 100%;
30+
height: 100%;
31+
padding: 16px;
32+
overflow: auto;
33+
}
34+
.@{prefix}-trigger-wrapper{
35+
top: 0;
36+
height: 100%;
37+
width: 0;
38+
.@{prefix}-move-trigger{
39+
position: absolute;
40+
top: 50%;
41+
height: @drag-drawer-trigger-height;
42+
width: @drag-drawer-trigger-width;
43+
background: rgb(243, 243, 243);
44+
transform: translate(-50%, -50%);
45+
border-radius: ~"4px / 6px";
46+
box-shadow: 0 0 1px 1px rgba(0, 0, 0, .2);
47+
line-height: @drag-drawer-trigger-height;
48+
cursor: col-resize;
49+
&-point{
50+
display: inline-block;
51+
width: 50%;
52+
transform: translateX(50%);
53+
i{
54+
display: block;
55+
border-bottom: 1px solid rgb(192, 192, 192);
56+
padding-bottom: 2px;
57+
}
58+
}
59+
}
60+
}
61+
.@{prefix}-footer{
62+
flex-grow: 1;
63+
width: 100%;
64+
bottom: 0;
65+
left: 0;
66+
border-top: 1px solid #e8e8e8;
67+
padding: 10px 16px;
68+
background: #fff;
69+
}
70+
}

Diff for: src/components/drag-drawer/mixin.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default {
2+
data () {
3+
return {
4+
prefix: 'drag-drawer'
5+
}
6+
}
7+
}

Diff for: src/libs/render-dom.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default {
2+
name: 'RenderDom',
3+
functional: true,
4+
props: {
5+
render: Function
6+
},
7+
render: (h, ctx) => {
8+
return ctx.props.render(h)
9+
}
10+
}

Diff for: src/locale/lang/en-US.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ export default {
3939
cropper_page: 'Cropper',
4040
message_page: 'Message Center',
4141
tree_table_page: 'Tree Table',
42-
org_tree_page: 'Org Tree'
42+
org_tree_page: 'Org Tree',
43+
drag_drawer_page: 'Draggable Drawer'
4344
}

Diff for: src/locale/lang/zh-CN.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ export default {
3939
cropper_page: '图片裁剪',
4040
message_page: '消息中心',
4141
tree_table_page: '树状表格',
42-
org_tree_page: '组织结构树'
42+
org_tree_page: '组织结构树',
43+
drag_drawer_page: '可拖动抽屉'
4344
}

Diff for: src/locale/lang/zh-TW.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ export default {
3939
cropper_page: '圖片裁剪',
4040
message_page: '消息中心',
4141
tree_table_page: '樹狀表格',
42-
org_tree_page: '組織結構樹'
42+
org_tree_page: '組織結構樹',
43+
drag_drawer_page: '可拖動抽屜'
4344
}

Diff for: src/router/routers.js

+9
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@ export default [
125125
},
126126
component: () => import('@/view/components/drag-list/drag-list.vue')
127127
},
128+
{
129+
path: 'drag_drawer_page',
130+
name: 'drag_drawer_page',
131+
meta: {
132+
icon: 'md-list',
133+
title: '可拖拽抽屉'
134+
},
135+
component: () => import('@/view/components/drag-drawer')
136+
},
128137
{
129138
path: 'org_tree_page',
130139
name: 'org_tree_page',

0 commit comments

Comments
 (0)