ant-design-vue modal 拖拽效果,绝对的顺滑,不粘连。

1. 新建一个指令js文件 " modalDrag.js" 文件

2. 拷贝如下代码:

import Vue from 'vue'

/* 调用示例
<a-modal v-drag-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
  <img alt="example" style="width: 100%" :src="previewImage" />
</a-modal> */

// v-drag-modal: 弹窗拖拽
Vue.directive('drag-modal', (el, binding, vnode, oldVnode) => {
  Vue.nextTick(() => {
    let { visible, destroyOnClose } = vnode.componentInstance
    if (!visible) return
    const isThemeModal = el.classList.contains('grid-theme')
    const dialogHeaderEl = isThemeModal ? el.querySelector('.ant-tabs-bar') : el.querySelector('.ant-modal-header')
    const dragDom = isThemeModal ? el.querySelector('.ant-modal') : el.querySelector('.ant-modal')
    // dialogHeaderEl.style.cursor = 'move';
    dialogHeaderEl.style.cssText += ';cursor:move;'
    // dragDom.style.cssText += ';top:0px;'

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function () {
      if (window.document.currentStyle) {
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()
    dialogHeaderEl.onmousedown = (e) => {
      // 禁止选中文字,防止拖拽时弹框粘鼠标
      document.onselectstart = function () {
        return false;
      }
      // 鼠标按下,计算当前元素距离可视区的距离
      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 - (isThemeModal ? 10 : 0)

      const minDragDomTop = dragDom.offsetTop
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight - (isThemeModal ? 10 : 0)
      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      let styT = sty(dragDom, 'top')

      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        // eslint-disable-next-line no-useless-escape
        styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
        // eslint-disable-next-line no-useless-escape
        styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
      } else {
        styL = +styL.replace(/\px/g, '')
        styT = +styT.replace(/\px/g, '')
      };
      // dialogHeaderEl 此处直接使用el 防止鼠标移动太快脱离范围,导致无法拖动
      el.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;`
      }

      el.onmouseup = function (e) {
        el.onmousemove = null
        dialogHeaderEl.onmouseup = null
      }

      document.onmouseup = function (e) {
        el.onmousemove = null
        dialogHeaderEl.onmouseup = null
        // 在抬起鼠标之后,取消禁用选择文字
        document.onselectstart = function () {
          return true;
        }
      }
    }
  })
})

3. 在main.js 文件引入 “ modalDrag.js" 文件,例如: 

import './core/directives/modalDrag'

4.  .vue 文件组件里应用指令 ” v-drag-modal”, 重启服务,运行就大功告成了! 

<a-modal v-drag-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">

  <img alt="example" style="width: 100%" :src="previewImage" />

</a-modal>

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
如果您使用的是ant-design-vue3的Modal组件,并尝试在关闭模态框时使用resetFields方法重置表单,但是发现该方法无效,可能是您的代码中存在一些问题。 首先,请确保您正确地引入了antd的Vue3组件库,并且使用了正确的版本。如果您不确定,请参考antd官方文档。 其次,请检查您的代码中是否正确使用了Form组件,并且已经将form对象绑定到了Modal组件中。例如,您的代码可能类似于以下代码片段: ```html <template> <a-modal v-model:visible="visible" @ok="handleOk" @cancel="handleCancel"> <a-form :form="form"> <!-- 表单控件 --> </a-form> </a-modal> </template> <script> import { defineComponent, reactive } from 'vue'; import { Modal, Form } from 'ant-design-vue'; export default defineComponent({ components: { 'a-modal': Modal, 'a-form': Form, }, setup() { const form = reactive({}); const visible = reactive(false); const handleOk = () => { form.resetFields(); // 重置表单 visible.value = false; // 关闭模态框 }; const handleCancel = () => { form.resetFields(); // 重置表单 visible.value = false; // 关闭模态框 }; return { form, visible, handleOk, handleCancel, }; }, }); </script> ``` 在上面的代码中,我们将表单对象`form`绑定到了Modal组件中,并在`handleOk`和`handleCancel`方法中使用了`form.resetFields()`方法来重置表单。如果您的代码类似于此,但仍然无法解决问题,请尝试检查您的表单控件是否正确绑定了`v-model`,以及是否正确使用了`name`属性。 如果您仍然无法解决问题,请尝试提供更多的代码或其他信息,以便我们更好地帮助您解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值