增加可拖动抽屉组件drag-drawer
This commit is contained in:
parent
e78f77fc76
commit
11209b0ada
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import DragDrawer from './drag-drawer.vue'
|
||||
export default DragDrawer
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
export default {
|
||||
data () {
|
||||
return {
|
||||
prefix: 'drag-drawer'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
export default {
|
||||
name: 'RenderDom',
|
||||
functional: true,
|
||||
props: {
|
||||
render: Function
|
||||
},
|
||||
render: (h, ctx) => {
|
||||
return ctx.props.render(h)
|
||||
}
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@ export default {
|
|||
cropper_page: '图片裁剪',
|
||||
message_page: '消息中心',
|
||||
tree_table_page: '树状表格',
|
||||
org_tree_page: '组织结构树'
|
||||
org_tree_page: '组织结构树',
|
||||
drag_drawer_page: '可拖动抽屉'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@ export default {
|
|||
cropper_page: '圖片裁剪',
|
||||
message_page: '消息中心',
|
||||
tree_table_page: '樹狀表格',
|
||||
org_tree_page: '組織結構樹'
|
||||
org_tree_page: '組織結構樹',
|
||||
drag_drawer_page: '可拖動抽屜'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<Card>
|
||||
<h3 style="padding: 10px 0;">drag-drawer组件是对iview的drawer组件的封装,在支持drawer所有api的基础上,支持可拖动和footer底部插槽</h3>
|
||||
<div style="padding: 10px 0">
|
||||
<b>
|
||||
方向
|
||||
<i-switch v-model="placement">
|
||||
<span slot="open">左</span>
|
||||
<span slot="close">右</span>
|
||||
</i-switch>
|
||||
</b>
|
||||
<b>
|
||||
是否可拖动
|
||||
<i-switch v-model="draggable"></i-switch>
|
||||
</b>
|
||||
<Button @click="showContainerBDrawer = !showContainerBDrawer" type="primary" style="margin-left: 10px">{{ showContainerBDrawer ? '关闭' : '打开' }}容器内抽屉</Button>
|
||||
<Button @click="showWindowBDrawer = true" type="primary" style="margin-left: 10px">打开全屏抽屉</Button>
|
||||
</div>
|
||||
<div class="drag-drawer-inner-box">
|
||||
<drag-drawer v-model="showContainerBDrawer"
|
||||
:width.sync="width2"
|
||||
min-width="30px"
|
||||
:inner="true"
|
||||
:transfer="false"
|
||||
:placement="placementComputed"
|
||||
:draggable="draggable"
|
||||
@on-resize="handleResize"
|
||||
:scrollable="true">
|
||||
<div slot="header">
|
||||
<Icon type="md-aperture" :size="18"></Icon>
|
||||
<b>这是标题</b>
|
||||
</div>
|
||||
<p v-for="n in 200" :key="n">{{ n }}</p>
|
||||
<div slot="footer">
|
||||
<p>123123</p>
|
||||
<p>21312</p>
|
||||
</div>
|
||||
</drag-drawer>
|
||||
</div>
|
||||
<drag-drawer v-model="showWindowBDrawer"
|
||||
:width.sync="width1"
|
||||
:min-width="300"
|
||||
:placement="placementComputed"
|
||||
:draggable="draggable"
|
||||
:scrollable="true">
|
||||
<div slot="header">
|
||||
<Icon type="md-aperture" :size="18"></Icon>
|
||||
<b>这是标题</b>
|
||||
</div>
|
||||
<Button @click="showBDrawer3 = true">显示多层</Button>
|
||||
<p v-for="n in 200" :key="n">{{ n }}</p>
|
||||
</drag-drawer>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DragDrawer from '_c/drag-drawer'
|
||||
export default {
|
||||
name: 'drag_drawer_page',
|
||||
components: {
|
||||
DragDrawer
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showWindowBDrawer: false,
|
||||
showContainerBDrawer: false,
|
||||
showBDrawer3: false,
|
||||
width1: 300,
|
||||
width2: 200,
|
||||
placement: false,
|
||||
draggable: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
placementComputed () {
|
||||
return this.placement ? 'left' : 'right'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleResize (event) {
|
||||
const { atMin } = event
|
||||
/* eslint-disable */
|
||||
console.log(atMin);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.drag-drawer-inner-box{
|
||||
position: relative;
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
background: pink;
|
||||
border: 1px solid pink;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue