快捷搜索:  汽车  科技

el-popper点击事件(ElmentUI的el-dialog拖拽最大化)

el-popper点击事件(ElmentUI的el-dialog拖拽最大化)<template> <div class="components-container"> <el-button type="primary" @click="dialogTableVisible = true"> open a Drag Dialog </el-button> <el-button type="primary" @click="openDialog()"> 拖拽弹窗1 </el-button> <el-button type="primary" @click="openDialog1()"> 拖拽弹窗

最近要做一个新项目,使用的是花裤衩大佬的vue-elment-admin框架,但是有需求是要求弹窗可以拖拽,并且要做成非模态形式,打不过产品经理,开始搞!!!

先看看写好的效果图吧,后面再优化:

el-popper点击事件(ElmentUI的el-dialog拖拽最大化)(1)

这是最小化效果

el-popper点击事件(ElmentUI的el-dialog拖拽最大化)(2)

弹出效果

话不多说 直接上代码吧,先是封装好的dialog: index.vue

<template> <el-dialog v-el-drag-dialog ref="dragDialog" class="dragDialog" :title="config.title" :fullscreen="isFullScreen" :visible.sync="config.dialogVisible" :append-to-body="true" :close-on-click-modal="false" :show-close="false" :width="config.width" :modal="config.modal" @close="closeDialogDom()" :class="isMiniSize? 'isMiniSize': ''" > <div v-show="!isMiniSize" slot="title" class="medium"> <div class="centers"><span>{{config.title}}</span></div> <div class="icons"> <i class="el-icon-minus" style="font-size: 24px" @click="minimize"></i> <i :class="isFullScreen? 'el-icon-remove-outline' : 'el-icon-circle-plus-outline' " style="font-size: 24px" @click="IsFullscreen"></i> <i class="el-icon-close" style="font-size: 24px" @click="closeDialog"></i> </div> </div> <div v-show="isMiniSize" slot="title" class="horn"> <div class="lefts"><span>{{config.title}}</span></div> <div class="centers"><i class="el-icon-circle-plus-outline" style="font-size: 24px" @click="backSize"></i></div> <div class="rights"><i class="el-icon-close" style="font-size: 24px" @click="closeDialog"></i></div> </div> <div v-show="!isMiniSize" class="dialogBody"> <slot></slot> </div> <div v-show="!isMiniSize" v-if="config.isFooter" class="dialogFooter"> <slot name="footer" solt="footer"> <el-button size="small" @click="config.dialogVisible = false">取 消</el-button> <el-button size="small" type="primary" @click="config.dialogVisible = false">确 定</el-button> </slot> </div> </el-dialog> </template> <script> import elDragDialog from './drag' export default { directives: { elDragDialog } props: { config: { type: Object default: () => ({}) } } data() { return { isFullScreen: false // 全屏 isMiniSize: false // 最小化 dialogVisible: false // 隐藏弹窗 } } watch: { config: { handler(newVal oldVal) { console.log(newVal) this.initDialog() } immediate: true } } methods: { // 初始化dialog initDialog() { // console.log(this.config) } // 最小化 minimize() { this.isMiniSize = !this.isMiniSize if (this.isFullScreen) this.isFullScreen = !this.isFullScreen this.$nextTick(() => { var miniSizeDom = document.getElementsByClassName('isMiniSize') miniSizeDom.forEach((item index) => { item.style.left = 240 * index 'px' }) }) } // 关闭回调 closeDialogDom() { this.$nextTick(() => { // dragDialog var miniSizeDom = document.getElementsByClassName('isMiniSize') console.log(miniSizeDom) miniSizeDom.forEach((item index) => { item.style.left = 240 * index 'px' }) }) } // 复原 backSize() { this.isMiniSize = !this.isMiniSize if (this.isFullScreen) this.isFullScreen = !this.isFullScreen this.$nextTick(() => { var dragDialogDom = document.getElementsByClassName('dragDialog') dragDialogDom.forEach((item index) => { item.style.left = 0 'px' }) var miniSizeDom = document.getElementsByClassName('isMiniSize') miniSizeDom.forEach((item index) => { item.style.left = 240 * index 'px' }) }) } // 关闭弹窗 closeDialog() { this.config.dialogVisible = false } // 打开弹窗 openDialog() { this.dialogVisible = true } // 全屏 IsFullscreen() { this.isFullScreen = !this.isFullScreen if (this.isFullScreen) this.$emit('isFullScreen') } } } </script> <style lang="scss"> // 覆盖层元素增加可穿透点击事件 .el-dialog__wrapper{ pointer-events: none !important; } // 弹窗元素不可穿透点击事件(不影响弹窗层的元素点击事件) .el-dialog{ pointer-events: auto !important; } .el-dialog{ margin-top: 10vh!important; } .no_select{ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .isMiniSize{ left: 20px; bottom: 20px; top: auto; right: auto; overflow:hidden; border-radius: 20px; margin: 0px 5px; .el-dialog { margin: 0 !important; width: 240px !important; height: 32px; top: 0 !important; left: 0 !important; } .el-dialog__header{ cursor: auto!important; background: #cccccc; .el-dialog__headerbtn { display: none; } } .dialogFooter{ position: absolute; bottom: 0; background: #cccccc; } } .dragDialog { .is-fullscreen { width: 100% !important; left: 0 !important; top: 0 !important; margin-top: 0 !important; overflow:hidden; position: relative; .el-dialog__header{ cursor: auto!important; } .el-dialog__body{ height: 100%; .dialogBody{ height:100%!important; max-height:none!important; padding-bottom:120px!important; } } .dialogFooter{ position: absolute; bottom: 0; width: 100%; background: #ccc; } } .el-dialog{ .el-dialog__header{ width: 100%; padding: 5px 20px 5px !important; display: flex; background: #ccc; border-bottom: 1px solid #ccc; @extend .no_select; cursor: auto; .medium{ width: 100%; height: 30px; line-height: 30px; display: flex; div{ flex:1; } .centers{ span{ text-align: center; font-size:16px; color:#606266; } } .icons{ display: flex; justify-content: flex-end; i{ color:#5f6368; font-size: 18px!important; display: block; padding:0 7px; } i:hover{ background: #dcdfe6; cursor: pointer; } .el-icon-close:hover{ background: #f00; color:#fff; } } } .horn{ width: 100%; height: 100%; display: flex; justify-content: space-between; div{ i{ color:#5f6368; font-size:20px!important; } } .lefts{ flex:4; margin-top: 3px; overflow: hidden; text-overflow:ellipsis; white-space: nowrap; span{ font-size: 16px; color:#606266; } } .centers{ flex:1; } .rights{ flex:1; } i:hover{ cursor: pointer; color:#000; } } .el-dialog__headerbtn { top: 0; font-size: 24px; } } .el-dialog__body{ padding: 1px !important; .dialogBody{ max-height: calc(80vh - 50px); overflow: auto; padding: 20px 25px 20px; &::-webkit-scrollbar { width: 4px; height: 8px; } &::-webkit-scrollbar-thumb { background: transparent; border-radius: 4px; } &:hover::-webkit-scrollbar-thumb { background: hsla(0 0% 53% .4) } &:hover::-webkit-scrollbar-track { background: hsla(0 0% 53% .1) } } .dialogFooter{ padding: 10px 15px; border-top: 1px solid #ccc; text-align: right; .el-button{ padding:7px 15px; } } } } .dragDialog{ .el-select{ width: 100%; } .el-date-editor{ width: 100%; } } } </style>

drag.js文件

export default { bind(el binding vnode oldVnode) { const dialogHeaderEl = el.querySelector('.el-dialog__header') const dragDom = el.querySelector('.el-dialog') dialogHeaderEl.style.cursor = 'move' // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素 null); const sty = dragDom.currentStyle || window.getComputedStyle(dragDom null) dialogHeaderEl.onmousedown = (e) => { // 判断当前是否为全屏状态 const path = event.path || (event.composedPath && event.composedPath()) const isFull = path.find(s => { if (s.className === undefined) { return false } else { return s.className.indexOf('is-fullscreen') > -1 } }) if (isFull !== undefined) { return } const isMinix = path.find(s => { if (s.className === undefined) { return false } else { return s.className.indexOf('isminimize') > -1 } }) if (isMinix !== undefined) { return } // 鼠标按下,计算当前元素距离可视区的距离 const disX = e.clientX - dialogHeaderEl.offsetLeft const disY = e.clientY - dialogHeaderEl.offsetTop // 获取到的值带px 正则匹配替换 let styL styT // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px if (sty.left.includes('%')) { styL = document.body.clientWidth * ( sty.left.replace(/\%/g '') / 100) styT = document.body.clientHeight * ( sty.top.replace(/\%/g '') / 100) } else { styL = sty.left.replace('px' '') styT = sty.top.replace('px' '') } document.onmousemove = function(e) { // 通过事件委托,计算移动的距离 const l = e.clientX - disX const t = e.clientY - disY // 移动当前元素 dragDom.style.left = `${l styL}px` dragDom.style.top = `${t styT}px` } document.onmouseup = function(e) { const dragDom = el.querySelector('.el-dialog') const offsetLeft = dragDom.offsetLeft const offsetTop = dragDom.offsetTop const left = Number(dragDom.style.left.replace('px' '')) const top = Number(dragDom.style.top.replace('px' '')) const windowWidth = window.innerWidth const windowHeight = window.innerHeight - 50 const offsetRight = offsetLeft dragDom.offsetWidth - windowWidth const offsetBottom = offsetTop dragDom.offsetHeight - windowHeight if (offsetLeft < 0) { dragDom.style.left = (left - offsetLeft) 'px' } if (offsetTop < 0) { dragDom.style.top = (top - offsetTop) 'px' } if (offsetRight > 0) { dragDom.style.left = (left - offsetRight) 'px' } if (offsetBottom > 0) { dragDom.style.top = (top - offsetBottom) 'px' } document.onmousemove = null document.onmouseup = null } } } }

下面这个是我们的父组件:drag-dialog.vue

<template> <div class="components-container"> <el-button type="primary" @click="dialogTableVisible = true"> open a Drag Dialog </el-button> <el-button type="primary" @click="openDialog()"> 拖拽弹窗1 </el-button> <el-button type="primary" @click="openDialog1()"> 拖拽弹窗2 </el-button> <el-button type="primary" @click="openDialog2()"> 拖拽弹窗3 </el-button> <el-dialog v-el-drag-dialog :visible.sync="dialogTableVisible" title="Shipping address" @dragDialog="handleDrag"> <el-select ref="select" v-model="value" placeholder="请选择"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-table :data="gridData"> <el-table-column property="date" label="Date" width="150" /> <el-table-column property="name" label="Name" width="200" /> <el-table-column property="address" label="Address" /> </el-table> </el-dialog> <drag-dialog v-if="dialogData.dialogVisible" :config="dialogData">1</drag-dialog> <drag-dialog v-if="dialogData1.dialogVisible" :config="dialogData1">2</drag-dialog> <drag-dialog v-if="dialogData2.dialogVisible" :config="dialogData2">3</drag-dialog> </div> </template> <script> import elDragDialog from '@/directive/el-drag-dialog' // base on element-ui import dragDialog from '@/components/DragDialog' export default { name: 'DragDialogDemo' components: { dragDialog } directives: { elDragDialog } data() { return { dialogData: { width: '50%' dialogVisible: false title: '拖拽1' modal: false isFooter: true } dialogData1: { width: '80%' dialogVisible: false title: '拖拽2' modal: false isFooter: true } dialogData2: { width: '80%' dialogVisible: false title: '拖拽3' modal: false isFooter: true } dialogTableVisible: false options: [ { value: '选项1' label: '黄金糕' } { value: '选项2' label: '双皮奶' } { value: '选项3' label: '蚵仔煎' } { value: '选项4' label: '龙须面' } ] value: '' gridData: [{ date: '2016-05-02' name: 'John Smith' address: 'No.1518 Jinshajiang Road Putuo District' } { date: '2016-05-04' name: 'John Smith' address: 'No.1518 Jinshajiang Road Putuo District' } { date: '2016-05-01' name: 'John Smith' address: 'No.1518 Jinshajiang Road Putuo District' } { date: '2016-05-03' name: 'John Smith' address: 'No.1518 Jinshajiang Road Putuo District' }] } } methods: { // v-el-drag-dialog onDrag callback function handleDrag() { this.$refs.select.blur() } openDialog() { this.dialogData.dialogVisible = true } openDialog1() { this.dialogData1.dialogVisible = true } openDialog2() { this.dialogData2.dialogVisible = true } } } </script>

话不多说,大佬们,各位兄弟们,有不明白的地方直接留言,看到都会及时回复。

猜您喜欢: