首页 > Vue >

vue的el-dialog拖拽拖动弹窗,包含不出可视窗口边界directives

时间: 作者:admin 浏览:

elementUI中的el-dialog弹窗,是常见的高使用率的一个组件,但却不支持拖动拖拽,查了一下资料,没查到满意的实现代码,还是自己写比较稳妥,于是就有了下面的v-dialogdrag自定义指令了,因为el-dialog自身的特定实现方式,所以此指令仅限使用在el-dialog上;
此指令还支持不超出可视窗口范围的参数v-dialogdrag.in,上代码:

template:

<el-dialog
    title="拖拽"
    :visible.sync="showDialog"
    width="30%"
    v-dialogdrag.in="showDialog"
></el-dialog>

javaScript:

export default {
    data(){
        return {
            showDialog: false
        }
    },
    directives:{
        dialogdrag:{
            bind(el, binding, vnode){
                let flag = true,
                    dialogOffsetLeft = 0,
                    dialogOffsetTop = 0,
                    dialogOffsetWidth = 0,
                    dialogOffsetHeight =0,
                    clientWidth = 0,
                    clientHeight = 0

                let dragDialog = (el, binding)=>{
                    let dialog = el.querySelector('.el-dialog')
                    let dialogHeader = el.querySelector('.el-dialog__header')
                    dialogHeader.style.cursor = "move"
                    dialogHeader.style.userSelect = "none"//防止选中内容
                    dialog.style.userSelect = "none"

                    dialogHeader.onmousedown(eDown)=>{
                        dialog.style.left = (dialog.style.left && dialog.style.left!='auto')?dialog.style.left : 0
                        dialog.style.top = (dialog.style.top && dialog.style.top!='auto')?dialog.style.top : 0

                        let beginLeft = parseInt(dialog.style.left), beginTop = parseInt(dialog.style.top)

                        dialogOffsetWidth = dialog.offsetWidth
                        dialogOffsetHeight = dialog.offsetHeight

                        if(flag){
                            dialogOffsetLeft = dialog.offsetLeft
                            dialogOffsetTop = dialog.offsetTop
                            flag = false
                        }

                        document.onmousemove = (eMove)=>{
                            clientWidth = el.clientWidth
                            clientHeight = el.clientHeight
                            let timer = setTimeout(()=>{//节流
                                if(binding.modifiers && binding.modifiers.in){
                                    //不超出可视窗口的情况
                                    let left = beginLeft + eMove.clientX - eDown.clientX
                                    let top = beginTop + eMove.clientY - eDown.clientY

                                    if(left >= -dialogOffsetLeft && (left + dialogOffsetWidth + dialogOffsetLeft) <= clientWidth){
                                        dialog.style.left = left + 'px'
                                    }else{
                                        //左右边界
                                        dialog.style.left = (left < 0?-dialogOffsetLeft : (clientWidth - dialogOffsetWidth - dialogOffsetLeft)) + 'px'
                                    }
                                    if(top >= -dialogOffsetTop && (top + dialogOffsetHeight + dialogOffsetTop) <= clientHeight){
                                        dialog.style.top = top + 'px'
                                    }else{
                                        //上下边界
                                        dialog.style.top = (top < 0?-dialogOffsetTop : (clientHeight - dialogOffsetHeight - dialogOffsetTop)) + 'px'
                                    }
                                }else{
                                    dialog.style.left = (beginLeft + eMove.clientX - eDown.clientX) + 'px'
                                    dialog.style.top = (beginTop + eMove.clientY - eDown.clientY) + 'px'
                                }
                                if(timer){
                                    clearTimeOut(timer)
                                    timer = null
                                }
                            },5)
                        }
                        document.onmouseup = (eUp)=>{
                            document.onmousemove = null
                            document.onmouseup = null
                        }
                    }
                    //窗口宽高变化也不超出可视窗口范围
                    window.addEventListener('resize', (e)=>{
                        dialogOffsetLeft = dialog.offsetLeft - parseInt((dialog.style.left && dialog.style.left!='auto')?dialog.style.left : 0)
                        dialogOffsetTop = dialog.offsetTop - parseInt((dialog.style.top && dialog.style.top!='auto')?dialog.style.top : 0)
                        //上下左右边界最大最小值
                        if(dialog.offsetLeft < 0){
                            dialog.style.left = -dialogOffsetLeft + 'px'
                        }
                        if(dialog.offsetRight < 0){
                            dialog.style.left = (el.clientWidth - dialogOffsetWidth - dialogOffsetLeft) + 'px'
                        }
                        if(dialog.offsetTop < 0){
                            dialog.style.top = -dialogOffsetTop + 'px'
                        }
                        if(dialog.offsetBottom < 0){
                            dialog.style.top = (el.clientHeight - dialogOffsetHeight - dialogOffsetTop) + 'px'
                        }
                    },false)
                }
                dragDialog(el, binding)
                vnode.context.dragDialog = dragDialog
            },
            componentUpdated(el, binding, vnode){
                if(typeof binding.value == 'boolean' && binding.value !== binding.oldValue){
                    if(binding.value){
                        vnode.context.dragDialog(el, binding)
                    }
                }
                if(binding.value === undefined){
                    vnode.context.dragDialog(el, binding)
                }
            }
        }
    }
}

参数说明:

v-dialogdrag.in="showDialog"中:

.in :非必填 | 是否只在可视窗口内拖拽

showDialog :Boolean | 非必填 | 窗口显示时才绑定拖拽功能(可传可不传,传了会减少点资源消耗)

前端新手交流群
欢迎加入web前端新手交流qq群:
734802480(已满)、 794324979

更多文章

栏目文章


Copyright © 2014-2022 seozhijia.net 版权所有-粤ICP备13087626号-4