vue实现可拖拽的dialog弹框


Posted in Vue.js onMay 13, 2021

本文主要介绍了vue实现可拖拽的dialog弹框,分享给大家,具体如下:

vue实现可拖拽的dialog弹框

element的dialog弹框在项目中挺常用的。但有时候嵌套的话会遮住,体验不好。拖拽形式的弹框会提高用户体验

借助基于 Sortable.js 的 Vue 拖拽组件vuedraggable

安装

npm install vuedraggable --save

在公共组件中新建个js文件,搭配vue自定义指令来实现拖拽的效果

import Vue from 'vue';
 
// v-dialogDrag: 弹窗拖拽属性
Vue.directive('dialogDrag', {
    bind(el, binding, vnode, oldVnode) {
        const dialogHeaderEl = el.querySelector('.el-dialog__header');
        const dragDom = el.querySelector('.el-dialog');
 
        dialogHeaderEl.style.cssText += ';cursor:move;'
        dragDom.style.cssText += ';top:0px;'
 
        // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
        const sty = (() => {
            if (window.document.currentStyle) {
                return (dom, attr) => dom.currentStyle[attr];
            } else {
                return (dom, attr) => getComputedStyle(dom, false)[attr];
            }
        })()
 
        dialogHeaderEl.onmousedown = (e) => {
            // 鼠标按下,计算当前元素距离可视区的距离
            const disX = e.clientX - dialogHeaderEl.offsetLeft;
            const disY = e.clientY - dialogHeaderEl.offsetTop;
 
            const screenWidth = document.body.clientWidth; // body当前宽度
            const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
 
            const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
            const dragDomheight = dragDom.offsetHeight; // 对话框高度
 
            const minDragDomLeft = dragDom.offsetLeft;
            const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
 
            const minDragDomTop = dragDom.offsetTop;
            const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
 
 
            // 获取到的值带px 正则匹配替换
            let styL = sty(dragDom, 'left');
            let styT = sty(dragDom, 'top');
 
            // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
            if (styL.includes('%')) {
                styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
                styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
            } else {
                styL = +styL.replace(/\px/g, '');
                styT = +styT.replace(/\px/g, '');
            };
 
            document.onmousemove = function (e) {
                // 通过事件委托,计算移动的距离
                let left = e.clientX - disX;
                let top = e.clientY - disY;
 
                // 边界处理
                if (-(left) > minDragDomLeft) {
                    left = -(minDragDomLeft);
                } else if (left > maxDragDomLeft) {
                    left = maxDragDomLeft;
                }
 
                if (-(top) > minDragDomTop) {
                    top = -(minDragDomTop);
                } else if (top > maxDragDomTop) {
                    top = maxDragDomTop;
                }
 
                // 移动当前元素 
                dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
            };
 
            document.onmouseup = function (e) {
                document.onmousemove = null;
                document.onmouseup = null;
            };
        }
    }
})

页面中使用 v-dialogDrag 即可实现想要的效果

<el-dialog
    v-dialogDrag
    :title="dialogTitle"
    :visible.sync="addDialogVisible"
    :before-close="handleClose"
    :close-on-click-modal="false"
    width="50%">
    <div class="add_columns">
        <div class="pull-organize">
            <div class="bm-title">部门管理</div>
            <el-tree
                :data="treeData"
                lazy:load="loadNode"
                accordion 
                :props="defaultProps"
                :default-expand-all="false">
            </el-tree>
        </div>
        <div class="show-information">
            <el-form inline>
                <el-form-item label="用户ID">
                    <el-input v-model="searchParams.userId" size="mini" ></el-input>
                </el-form-item>
                <el-form-item label="用户名">
                    <el-input v-model="searchParams.userName" size="mini"></el-input>
                </el-form-item>
                <el-form-item class="btn-item">
                    <el-button type="primary" @click="handleQuery" size="mini">查询</el-button>
                </el-form-item>
                    <el-form-item class="btn-item">
                    <el-button type="success" @click="hadnleAddPerson" size="mini">添加人员</el-button>
                </el-form-item>
            </el-form>
            <el-table
                :data="tableData"
                class="oneTabel"
                style="width:100%;">
                <el-table-column type="selection" width="50"></el-table-column>
                <el-table-column prop="id" width="60" label="登录ID"></el-table-column>
                <el-table-column prop="userName" label="用户名"></el-table-column>
                <el-table-column prop="education" label="部门"></el-table-column>
                <el-table-column prop="sex" label="手机"></el-table-column>
            </el-table>
        </div>
    </div>
</el-dialog>

到此这篇关于vue实现可拖拽的dialog弹框的文章就介绍到这了,更多相关vue 可拖拽弹框内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
深入了解Vue3模板编译原理
Nov 19 Vue.js
VUE项目实现主题切换的多种方法
Nov 26 Vue.js
vue+element_ui上传文件,并传递额外参数操作
Dec 05 Vue.js
vuex页面刷新导致数据丢失的解决方案
Dec 10 Vue.js
vue中封装axios并实现api接口的统一管理
Dec 25 Vue.js
vue中activated的用法
Jan 03 Vue.js
Vue页面渲染中key的应用实例教程
Jan 12 Vue.js
vue中axios封装使用的完整教程
Mar 03 Vue.js
Vue Element UI自定义描述列表组件
May 18 Vue.js
Vue CLI中模式与环境变量的深入详解
May 30 Vue.js
Vue中foreach数组与js中遍历数组的写法说明
Jun 05 Vue.js
vue判断按钮是否可以点击
Apr 09 Vue.js
vue如何批量引入组件、注册和使用详解
vue组件的路由高亮问题解决方法
Vue通过懒加载提升页面响应速度
Vue详细的入门笔记
如何理解Vue前后端数据交互与显示
Vue实现下拉加载更多
May 09 #Vue.js
如何使用vue3打造一个物料库
You might like
PHP 存取 MySQL 数据库的一个例子
2006/10/09 PHP
探讨:使用XMLSerialize 序列化与反序列化
2013/06/08 PHP
ThinkPHP实现支付宝接口功能实例
2014/12/02 PHP
javascript 通用简单的table选项卡实现
2010/05/07 Javascript
jquery多浏览器捕捉回车事件代码
2010/06/22 Javascript
Javascript 面试题随笔
2011/03/31 Javascript
50个比较实用jQuery代码段
2011/09/18 Javascript
js模拟C#中List的简单实例
2014/03/06 Javascript
js实现浏览器窗口大小被改变时触发事件的方法
2015/02/02 Javascript
JS前端加密算法示例
2016/12/22 Javascript
利用Javascript实现简单的转盘抽奖
2017/02/13 Javascript
微信小程序支付之c#后台实现方法
2017/10/19 Javascript
基于vue中解决v-for使用报红并出现警告的问题
2018/03/03 Javascript
vue 使用vue-i18n做全局中英文切换的方法
2018/10/29 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
Vue切换组件实现返回后不重置数据,保留历史设置操作
2020/07/21 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
[48:18]DOTA2-DPC中国联赛 正赛 RNG vs Dynasty BO3 第二场 1月29日
2021/03/11 DOTA
深入解析Python设计模式编程中建造者模式的使用
2016/03/02 Python
详解python脚本自动生成需要文件实例代码
2017/02/04 Python
pytorch cnn 识别手写的字实现自建图片数据
2018/05/20 Python
python3 flask实现文件上传功能
2020/03/20 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
2019/05/23 Python
python实现数据分析与建模
2019/07/11 Python
python使用paramiko模块通过ssh2协议对交换机进行配置的方法
2019/07/25 Python
Python 生成短8位唯一id实战教程
2021/01/13 Python
浅谈HTML5新增及移除的元素
2016/06/27 HTML / CSS
如何让pre和textarea等HTML元素去掉滚动条自动换行自适应文本内容高度
2019/08/01 HTML / CSS
Draper James官网:知名演员瑞茜·威瑟斯彭所创品牌
2017/10/25 全球购物
Farfetch阿联酋:奢侈品牌时尚购物平台
2019/07/26 全球购物
乌克兰第一的珠宝网上商店:Gold.ua
2019/11/29 全球购物
党日活动总结
2014/05/07 职场文书
客运企业隐患排查工作方案
2014/06/06 职场文书
MySQL Router的安装部署
2021/04/24 MySQL
AudioContext 实现音频可视化(web技术分享)
2022/02/24 Javascript
Redis实现订单过期删除的方法步骤
2022/06/05 Redis