Vue+Elementui 弹窗全局配置第二版 监听鼠标是否移除浏览器

<template>
  <div></div>
</template>

<script>
  export default {
    name: 'dialogDrag',
    data() {
      return {
        originalWidth: null,
        originalHeight: null,
        lastMousemoveHandler: null,
        lastMouseupHandler: null,
        mousedown: false
      }
    },

    created() {

    },
    mounted() {
      this.$nextTick(() => {
        this.dialogDrag()
      })
    },
    beforeDestroy() {
      this.clearLastEvents()
    },

    methods: {
      // 清除事件监听
      clearLastEvents() {
        this.mousedown = false
        if (this.lastMousemoveHandler) {
          document.removeEventListener('mousemove', this.lastMousemoveHandler)
          this.lastMousemoveHandler = null
        }
        if (this.lastMouseupHandler) {
          document.body.removeEventListener('mouseup', this.lastMouseupHandler)
          document.removeEventListener('mouseup', this.lastMouseupHandler)
          this.lastMouseupHandler = null
        }
      },

      // 处理窗口大小
      handleDialogSize(dragDom) {
        if (this.originalWidth || this.originalHeight) {
          // 还原弹窗的宽度和高度
          dragDom.style.width = this.originalWidth
          dragDom.style.height = this.originalHeight
          this.originalWidth = null
          this.originalHeight = null
        } else {
          // 保存当前弹窗的宽度和高度
          this.originalWidth = dragDom.style.width
          this.originalHeight = dragDom.style.height
          // 设置弹窗宽度和高度为窗口的宽度和高度
          dragDom.style.width = '100vw'
          dragDom.style.height = window.innerHeight + 'px'
          dragDom.style.overflow = 'auto'
        }
      },

      dialogDrag() {
        // 获取弹窗DOM
        const dragDom = this.$el.getElementsByClassName('el-dialog')[0]
        if (!dragDom) return

        // 弹窗标题顶部DOM
        const dialogHeaderDom = this.$el.getElementsByClassName('el-dialog__header')[0]
        if (!dialogHeaderDom) return

        // 设置拖动样式
        dialogHeaderDom.style.cursor = 'move'
        dialogHeaderDom.style.userSelect = 'none'
// 初始化弹窗位置为居中
//         this.$nextTick(() => {
//           setTimeout(() => {
//             // 1. 获取弹窗宽度
//             const dialogWidth = dragDom.offsetWidth/2
//             console.log('弹窗宽度:', dialogWidth)
//
//             // 2. 获取浏览器窗口宽度
//             const windowWidth = document.documentElement.clientWidth/2
//             console.log('窗口宽度:', windowWidth)
//
//             // 3. 计算左边距:(窗口宽度 - 弹窗宽度) / 2
//             const left = windowWidth - dialogWidth
//             console.log('计算的左边距:', left)
//
//             // 设置弹窗位置
//             dragDom.style.left = `${left}px`
//             dragDom.style.top = '2vh'
//           }, 500)
//         })
        const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)

        dialogHeaderDom.onmousedown = (e) => {
          // 清除上一次的事件监听
          this.clearLastEvents()

          // 处理双击
          if (e.detail === 2) {
            this.handleDialogSize(dragDom)
            return
          }

          // 阻止默认事件和冒泡
          e.stopPropagation()
          e.preventDefault()

          this.mousedown = true

          // 获取鼠标按下时的位置
          const startLeft = e.clientX - dialogHeaderDom.offsetLeft
          const startTop = e.clientY - dialogHeaderDom.offsetTop

          // 获取当前窗口的位置
          let styL, styT

          if (sty.left.includes('%')) {
            styL = +document.body.clientWidth * (+sty.left.replace('%', '') / 100)
            styT = +document.body.clientHeight * (+sty.top.replace('%', '') / 100)
          } else {
            styL = +sty.left.replace('px', '')
            styT = +sty.top.replace('px', '')
          }

          // 鼠标移动事件处理
          const handleMouseMove = (e) => {
            if (!this.mousedown) return false

            // 计算新位置
            let l = e.clientX - startLeft + styL
            let t = e.clientY - startTop + styT

            // 获取可移动的边界
            const offsetParent = dragDom.offsetParent || document.body
            const maxL = offsetParent.clientWidth - dragDom.clientWidth
            const maxT = offsetParent.clientHeight - dragDom.clientHeight +
              (sty.height.toString().split('p') && Number(sty.height.toString().split('p')[0])/1.5)

            // 限制移动范围
            l = Math.min(Math.max(l, -dragDom.clientWidth), maxL)
            t = Math.min(Math.max(t, 0), maxT)

            // 更新位置
            dragDom.style.left = `${l}px`
            dragDom.style.top = `${t}px`

            // 检查鼠标是否在有效范围内
            if (e.clientY <= 0 || e.clientY >= window.innerHeight ||
              e.clientX <= 0 || e.clientX >= window.innerWidth) {
              this.clearLastEvents()
            }
          }

          // 鼠标释放事件处理
          const handleMouseUp = () => {
            this.clearLastEvents()
          }

          // 保存事件处理函数
          this.lastMousemoveHandler = handleMouseMove
          this.lastMouseupHandler = handleMouseUp

          // 添加事件监听
          document.addEventListener('mousemove', handleMouseMove)
          document.addEventListener('mouseup', handleMouseUp)
          document.body.addEventListener('mouseup', handleMouseUp)

          // 添加鼠标离开窗口的监听
          document.addEventListener('mouseleave', (e) => {
            if (this.mousedown) {
              if (e.clientY <= 0 || e.clientY >= window.innerHeight ||
                e.clientX <= 0 || e.clientX >= window.innerWidth) {
                this.clearLastEvents()
              }
            }
          })
        }
      }
    }
  }
</script>

<style scoped>

</style>

全局配置参考文档

Vue2+ElementUI 弹窗全局拖拽 支持放大缩小_element plus 缩小弹窗-CSDN博客

相关推荐
fangcaojushi6 分钟前
解决webpack5.54打包图片及图标的问题
前端·vue.js
前端菜鸟日常20 分钟前
vue2和vue3的按需引入的详细对比通俗易懂
javascript·vue.js·ecmascript
AC-PEACE35 分钟前
Vue 中 MVVM、MVC 和 MVP 模式的区别
前端·vue.js·mvc
冷琴19961 小时前
基于Python+Vue开发的反诈视频宣传管理系统源代码
开发语言·vue.js·python
m0_748257462 小时前
创建一个简单的spring boot+vue前后端分离项目
vue.js·spring boot·后端
祈澈菇凉2 小时前
除了Axios,如何用fetch处理403错误?
前端·javascript·vue.js
草字2 小时前
vue,vue3 keepalive没有效果,无法缓存页面include无效,keep-alive
前端·vue.js·缓存
JSON_L2 小时前
Vue Axios
前端·javascript·vue.js
柳鲲鹏2 小时前
Ubuntu编译jetlinks-ui-vue
vue.js·ui
小王不会写code3 小时前
Vue.prototype 详解及使用
前端·javascript·vue.js