Skip to content

Commit

Permalink
增加可拖动抽屉组件drag-drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
lison16 committed Dec 21, 2018
1 parent e78f77f commit 11209b0
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 3 deletions.
18 changes: 18 additions & 0 deletions src/components/drag-drawer/drag-drawer-trigger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div :class="`${prefix}-move-trigger`">
<div :class="`${prefix}-move-trigger-point`">
<i></i><i></i><i></i><i></i><i></i>
</div>
</div>
</template>

<script>
import Mixin from './mixin'
export default {
name: 'DragDrawerTrigger',
mixins: [Mixin]
}
</script>

<style>
</style>
156 changes: 156 additions & 0 deletions src/components/drag-drawer/drag-drawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<template>
<Drawer ref="drawerWrapper"
:value="value"
@input="handleInput"
:width="width"
:class-name="outerClasses"
v-bind="$attrs"
v-on="$listeners">
<!-- 所有插槽内容显示在这里 ↓ -->

<template v-for="(slots, slotsName) in $slots">
<template v-if="slotsName !== 'default'">
<render-dom v-for="(render, index) in slots"
:key="`b_drawer_${slotsName}_${index}`"
:render="() => render"
:slot="slotsName">
</render-dom>
</template>
<template v-else>
<div :class="`${prefix}-body-wrapper`"
:key="`b_drawer_${slotsName}`">
<render-dom v-for="(render, index) in slots"
:key="`b_drawer_${slotsName}_${index}`"
:render="() => render"
:slot="slotsName">
</render-dom>
</div>
</template>
</template>
<!-- 所有插槽内容显示在这里 ↑ -->
<div v-if="draggable"
:style="triggerStyle"
:class="`${prefix}-trigger-wrapper`"
@mousedown="handleTriggerMousedown">
<slot name="trigger">
<drag-drawer-trigger></drag-drawer-trigger>
</slot>
</div>
<div v-if="$slots.footer"
:class="`${prefix}-footer`">
<slot name="footer"></slot>
</div>
</Drawer>
</template>

<script>
import RenderDom from '@/libs/render-dom'
import DragDrawerTrigger from './drag-drawer-trigger.vue'
import Mixin from './mixin'
import { on, off } from '@/libs/tools'
import './index.less'
export default {
name: 'BDrawer',
components: {
RenderDom,
DragDrawerTrigger
},
mixins: [Mixin],
props: {
value: {
type: Boolean,
default: false
},
width: {
type: [String, Number],
default: 256
},
// 是否可拖动修改宽度
draggable: {
type: Boolean,
default: false
},
// 最小拖动宽度
minWidth: {
type: [String, Number],
default: 256
}
},
data () {
return {
canMove: false,
wrapperWidth: 0,
wrapperLeft: 0
}
},
computed: {
outerClasses () {
const classesArray = [
`${this.prefix}-wrapper`,
this.canMove ? 'no-select pointer-events-none' : ''
]
return classesArray.join(' ')
},
placement () {
return this.$attrs.placement
},
innerWidth () {
const width = this.width
return width <= 100 ? (this.wrapperWidth * width) / 100 : width
},
triggerStyle () {
return {
[this.placement]: `${this.innerWidth}px`,
position: this.$attrs.inner ? 'absolute' : 'fixed'
}
}
},
methods: {
handleInput (status) {
this.$emit('input', status)
},
handleTriggerMousedown (event) {
this.canMove = true
this.$emit('on-resize-start')
// 防止鼠标选中抽屉中文字,造成拖动trigger触发浏览器原生拖动行为
window.getSelection().removeAllRanges()
},
handleMousemove (event) {
if (!this.canMove) return
// 更新容器宽度和距离左侧页面距离,如果是window则距左侧距离为0
this.setWrapperWidth()
const left = event.pageX - this.wrapperLeft
// 如果抽屉方向为右边,宽度计算需用容器宽度减去left
let width = this.placement === 'right' ? this.wrapperWidth - left : left
// 限定做小宽度
width = Math.max(width, parseFloat(this.minWidth))
event.atMin = width === parseFloat(this.minWidth)
// 如果当前width不大于100,视为百分比
if (width <= 100) width = (width / this.wrapperWidth) * 100
this.$emit('update:width', parseInt(width))
this.$emit('on-resize', event)
},
handleMouseup (event) {
this.canMove = false
this.$emit('on-resize-end')
},
setWrapperWidth () {
const {
width,
left
} = this.$refs.drawerWrapper.$el.getBoundingClientRect()
this.wrapperWidth = width
this.wrapperLeft = left
}
},
mounted () {
on(document, 'mousemove', this.handleMousemove)
on(document, 'mouseup', this.handleMouseup)
this.setWrapperWidth()
},
beforeDestroy () {
off(document, 'mousemove', this.handleMousemove)
off(document, 'mouseup', this.handleMouseup)
}
}
</script>
2 changes: 2 additions & 0 deletions src/components/drag-drawer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import DragDrawer from './drag-drawer.vue'
export default DragDrawer
70 changes: 70 additions & 0 deletions src/components/drag-drawer/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@prefix: ~"drag-drawer";
@drag-drawer-trigger-height: 100px;
@drag-drawer-trigger-width: 8px;

.@{prefix}-wrapper{
&.no-select{
user-select: none;
}
&.pointer-events-none{
pointer-events: none;
& .@{prefix}-trigger-wrapper{
pointer-events: all;
}
}
.ivu-drawer{
&-header{
overflow: hidden !important;
box-sizing: border-box;
}
&-body{
padding: 0;
overflow: visible;
position: static;
display: flex;
flex-direction: column;
}
}
.@{prefix}-body-wrapper{
width: 100%;
height: 100%;
padding: 16px;
overflow: auto;
}
.@{prefix}-trigger-wrapper{
top: 0;
height: 100%;
width: 0;
.@{prefix}-move-trigger{
position: absolute;
top: 50%;
height: @drag-drawer-trigger-height;
width: @drag-drawer-trigger-width;
background: rgb(243, 243, 243);
transform: translate(-50%, -50%);
border-radius: ~"4px / 6px";
box-shadow: 0 0 1px 1px rgba(0, 0, 0, .2);
line-height: @drag-drawer-trigger-height;
cursor: col-resize;
&-point{
display: inline-block;
width: 50%;
transform: translateX(50%);
i{
display: block;
border-bottom: 1px solid rgb(192, 192, 192);
padding-bottom: 2px;
}
}
}
}
.@{prefix}-footer{
flex-grow: 1;
width: 100%;
bottom: 0;
left: 0;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
background: #fff;
}
}
7 changes: 7 additions & 0 deletions src/components/drag-drawer/mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
data () {
return {
prefix: 'drag-drawer'
}
}
}
10 changes: 10 additions & 0 deletions src/libs/render-dom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
name: 'RenderDom',
functional: true,
props: {
render: Function
},
render: (h, ctx) => {
return ctx.props.render(h)
}
}
3 changes: 2 additions & 1 deletion src/locale/lang/en-US.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ export default {
cropper_page: 'Cropper',
message_page: 'Message Center',
tree_table_page: 'Tree Table',
org_tree_page: 'Org Tree'
org_tree_page: 'Org Tree',
drag_drawer_page: 'Draggable Drawer'
}
3 changes: 2 additions & 1 deletion src/locale/lang/zh-CN.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ export default {
cropper_page: '图片裁剪',
message_page: '消息中心',
tree_table_page: '树状表格',
org_tree_page: '组织结构树'
org_tree_page: '组织结构树',
drag_drawer_page: '可拖动抽屉'
}
3 changes: 2 additions & 1 deletion src/locale/lang/zh-TW.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ export default {
cropper_page: '圖片裁剪',
message_page: '消息中心',
tree_table_page: '樹狀表格',
org_tree_page: '組織結構樹'
org_tree_page: '組織結構樹',
drag_drawer_page: '可拖動抽屜'
}
9 changes: 9 additions & 0 deletions src/router/routers.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ export default [
},
component: () => import('@/view/components/drag-list/drag-list.vue')
},
{
path: 'drag_drawer_page',
name: 'drag_drawer_page',
meta: {
icon: 'md-list',
title: '可拖拽抽屉'
},
component: () => import('@/view/components/drag-drawer')
},
{
path: 'org_tree_page',
name: 'org_tree_page',
Expand Down
Loading

1 comment on commit 11209b0

@wangliguokaka
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my vue version is 2.9.6
drag-drawer doesn't word, please confirm it.

Please sign in to comment.