el-dialog实现拖拽

本文介绍了如何在Vue应用中使用自定义指令`dialogDrag`,实现el-dialog组件的拖拽功能。通过`v-dialogDrag`指令,允许用户轻松调整对话框的位置,提高用户体验。主要涉及`install`方法的实现和在`main.js`中的导入与使用,适用于前端开发场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、自定义指令文件

  • el-dialog/index.js




const vueDialogDrag = {}
vueDialogDrag.install = 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.cursor = 'move'
      el.style.overflow = "hidden"
      // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
      const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)

      dialogHeaderEl.onmousedown = (e) => {
        // 鼠标按下,计算当前元素距离可视区的距离
        const disX = e.clientX - dialogHeaderEl.offsetLeft
        const disY = e.clientY - dialogHeaderEl.offsetTop
        // 获取可视区域
        const cliW = document.documentElement.clientWidth
        const cliH = document.documentElement.clientHeight
        // 获取到的值带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/g, '')
          styT = +sty.top.replace(/\px/g, '')
        }

        document.onmousemove = function (e) {

          // 通过事件委托,计算移动的距离
          let left = e.clientX - disX
          let top = e.clientY - disY

          // 移动当前元素 边界处理
          if ((disX + left > 100) && (disX + left + 100 < cliW)) {
            dragDom.style.left = `${left + styL}px`
          }
          if ((disY + top > 25) && (disY + top + 85 < cliH)) {
            dragDom.style.top = `${top + styT}px`
          }
        }

        document.onmouseup = function (e) {
          document.onmousemove = null
          document.onmouseup = null
        }
      }
    }
  })
}
export default vueDialogDrag



2、main.js文件

import vueDialogDrag from '@/directive/el-dialog' // 拖拽
vueDialogDrag.install(Vue)

3、页面使用

我这里就不写其他参数了,知道怎么用就可以啦!

 <el-dialog v-dialogDrag> </el-dialog>
### 实现 `el-dialog` 组件在其父容器内可拖拽 为了实现 `el-dialog` 对话框仅能在其父容器内部进行拖拽,可以创建自定义指令来控制这一行为。通过监听鼠标事件并计算相对位置,确保对话框不会超出父容器边界。 #### 创建自定义指令文件 `directive.js` 此文件用于封装拖拽逻辑: ```javascript // directive.js export default { inserted(el, binding) { const dialogHeaderEl = el.querySelector('.el-dialog__header'); const dragDom = el.querySelector('.el-dialog'); let isDragging = false; let startX, startY, offsetX, offsetY; function handleMouseDown(e) { e.preventDefault(); isDragging = true; startX = e.clientX - offsetX; startY = e.clientY - offsetY; document.onmousemove = handleMouseMove; document.onmouseup = handleMouseUp; } function handleMouseMove(e) { if (!isDragging) return; // 获取父容器尺寸和位置 const parentRect = el.parentElement.getBoundingClientRect(); let newLeft = e.clientX - startX + offsetX; let newTop = e.clientY - startY + offsetY; // 计算最大最小坐标防止溢出 newLeft = Math.max(0, Math.min(newLeft, parentRect.width - dragDom.offsetWidth)); newTop = Math.max(0, Math.min(newTop, parentRect.height - dragDom.offsetHeight)); dragDom.style.left = `${newLeft}px`; dragDom.style.top = `${newTop}px`; // 更新偏移量以便下次移动 offsetX = parseInt(dragDom.style.left); offsetY = parseInt(dragDom.style.top); } function handleMouseUp() { isDragging = false; document.onmousemove = null; document.onmouseup = null; } dialogHeaderEl && dialogHeaderEl.addEventListener('mousedown', (e) => { const { offsetWidth: width, offsetHeight: height } = dragDom; offsetX = dragDom.offsetLeft; offsetY = dragDom.offsetTop; handleMouseDown(e); }); // 初始化样式以适应父容器定位 dragDom.style.position = 'absolute'; dragDom.style.left = '0px'; dragDom.style.top = '0px'; // 设置初始位置居中显示 setTimeout(() => { dragDom.style.left = `${((parentRect.width - width) / 2)}px`; dragDom.style.top = `${((parentRect.height - height) / 2)}px`; }, 100); // 延迟执行让DOM渲染完成再调整位置 } } ``` #### 修改 `main.js` 导入自定义指令 在项目的入口文件中注册这个全局指令: ```javascript import Vue from 'vue' import App from './App.vue' import directives from '@/utils/directive' // 路径可能需要根据实际情况修改 Vue.config.productionTip = false Vue.use(directives) new Vue({ render: h => h(App), }).$mount('#app') ``` #### 使用带有 `v-dialogDrag` 的 `el-dialog` 最后,在模板中应用该指令即可启用拖拽功能: ```html <template> <div class="container"> <!-- 父容器 --> <el-button @click="dialogVisible = true">打开Dialog</el-button> <el-dialog :visible.sync="dialogVisible" v-dialogDrag> <span slot="title"><i>这是标题</i></span> 这里是内容... </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, }; }, }; </script> <style scoped> .container { position: relative; /* 定义合适的宽高 */ width: 80vw; height: 80vh; border: 1px solid black; } /* 可选:为对话框设置一些默认样式 */ .el-dialog { max-width: calc(100% - 40px); max-height: calc(100% - 40px); box-shadow: none !important; } </style> ``` 上述方法实现了 `el-dialog` 在指定父容器内的自由拖拽效果[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

守望黑玫瑰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值