记录一下vue2项目的一个自定义拖拽指令

需求是聊天框图标可以在页面范围内上下被拖拽且不能超出页面范围,并且在拖拽的同时不能触发按钮的点击事件,单独点击时才打开弹框

 

#html
<div class="groundChat" v-draggable></div>
#指令
directives: {//自定义指令,拖拽
    draggable: {
      bind: function (el, binding, vnode) {
        el.style.position = 'fixed'; // 设置元素为 fixed 定位
        const _el = el; // 获取当前元素
        const ref = vnode.context.$refs[binding.value]; // 判断基于移动的是哪一个盒子
        const masterNode = ref ? ref : document; // 用于绑定事件
        const masterBody = ref ? ref : document.body; // 用于获取高和宽
        const maxHeight = masterBody.clientHeight; // 窗口可见区域的高度
        const elHeight = _el.clientHeight; // 元素自身的高度
        let disX = 0, disY = 0; // 鼠标按下时的偏移量
        let isDragging = false; // 是否正在拖动的标志
        let isClick = false; // 是否是点击
        function handleMouseDown(e) { // 鼠标落下
          if (isDragging) { // 如果已经在拖动中,则直接返回
            return;
          }
          e.preventDefault(); // 阻止默认事件,例如文本框的选中
          isDragging = true; // 设置正在拖动的标志为 true
          isClick = true; // 设置点击标志为 true
          // disX = e.clientX - _el.offsetLeft; // 计算鼠标按下时的横向偏移量
          disY = e.clientY - _el.offsetTop; // 计算鼠标按下时的纵向偏移量
          masterNode.addEventListener('mousemove', dragElement); // 绑定鼠标移动事件
          masterNode.addEventListener('mouseup', handleMouseUp); // 绑定鼠标松开事件
          // 监听窗口的 resize 事件,重新获取可见区域的宽度和高度
          window.addEventListener('resize', handleResize);
        }
        function dragElement(e) { // 拖拽的计算
          if (isDragging) { // 如果正在拖动,则执行拖动操作
            let top = e.clientY - disY; // 计算拖动后的纵向偏移量
            top = Math.min(top, maxHeight - elHeight - 70); // 这里使用 Math.min 来确保不超出底部边界,70是元素的高度要计算进去
            top = Math.max(top, 0); // 使用 Math.max 确保不超出顶部边界
            _el.style.top = top + 'px'; // 设置元素的纵向位置
            isClick = false; // 拖拽的时候设置 isClick 为 false,不让触发打开弹框的事件
          }
        }
        function handleMouseUp() { // 鼠标松开
          isDragging = false; // 设置正在拖动的标志为 false
          masterNode.removeEventListener('mousemove', dragElement); // 解绑鼠标移动事件
          masterNode.removeEventListener('mouseup', handleMouseUp); // 解绑鼠标松开事件
          window.removeEventListener('resize', handleResize); // 解绑窗口 resize 事件
        }
        function handleResize() { // 窗口 resize 事件处理程序
          maxWidth = masterBody.clientWidth; // 更新可见区域宽度
          maxHeight = masterBody.clientHeight; // 更新可见区域高度
        }
        _el.addEventListener('mousedown', handleMouseDown); // 绑定鼠标按下事件
        // 点击事件处理程序
        vnode.context.handleClick = e => {
          if (!isDragging && isClick) { // 如果不是拖动状态且是点击操作,则执行相应的逻辑
            vnode.context.showTips(); // 调用组件实例的 showTips 方法
          }
        };
      },
      inserted(el, binding, vnode) {
        el.addEventListener('click', vnode.context.handleClick); // 绑定点击事件
      },
      unbind(el, binding, vnode) {
        el.removeEventListener('click', vnode.context.handleClick); // 解绑点击事件
      }
    }
  },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值