解决vue @mouseup之后默认触发@click

489 阅读2分钟

需求:一个可以全局拖动的浮窗。
做完后
领导: 给这个浮窗加一个点击效果
FXXX,你怎么不上天

没办法作为社畜只能埋头干。可是做完之后发现拖拽完成之后会默认触发绑定的click事件

原始代码

<template>
  <div 
    class="dragBox"
    ref="dragBox"
    @mousedown="startDrag"
    @mousemove="drag"
    @mouseup="stopDrag"
    @click="handleMask"></div>
</template>

<script>

export default {
  data() {
    return {
      mousehasDown: false,
    };
  },
  methods: {
    // 鼠标按下的时候记录坐标信息
    startDrag(event) {
      console.log("鼠标按下");
      this.mousehasDown = true
      // 省略了一些变量声明,不会取名就不拿出来献丑了
    },
    // 拖拽进行
    drag(event) {
      if (this.mousehasDown) {
        // 下面是一些拖拽时候的优化就省略了
      }
    },
    // 停止拖拽
    stopDrag(event) {
      this.mousehasDown = false
    },
    handleMask() {
      console.log('这里是点击事件');
  },
};
</script>

<style>
.count {
  color: red;
}
</style>
      

解决过程

后面查了各位过来人的方法,最多的是在mousedown的方法使用event.preventDefault去阻止默认事件触发。但是在我这儿并没生效。
由于当时开发时间比较紧急,我也只好自己看看有没有其他方法可以解决这个问题。然后就想看看能不能从事件的触发顺序中下手去看看。单个鼠标点击事件的触发顺序是 mousedown -> mouseup -> click 加上拖拽之后是 mousedown -> mousemove -> mouseup -> click,这些事件都是宏事件,在JS中都是同步往下执行。这就让我找到了一个解决方法。\

解决办法

在全局增加一个变量去监控是否执行了拖拽。通过JS的宏/微任务机制去阻止click事件的触发

<template>
  <div 
    class="dragBox"
    ref="dragBox"
    @mousedown="startDrag"
    @mousemove="drag"
    @mouseup="stopDrag"
    @click="handleMask"></div>
</template>

<script>

export default {
  data() {
    return {
      mousehasDown: false,
    };
  },
  methods: {
    // 鼠标按下的时候记录坐标信息
    startDrag(event) {
      console.log("鼠标按下");
      this.mousehasDown = true
      // 省略了一些变量声明,不会取名就不拿出来献丑了
    },
    // 拖拽进行
    drag(event) {
      if (this.mousehasDown) {
        this.dragging = true;
        // 下面是一些拖拽时候的优化就省略了
      }
    },
    // 停止拖拽
    stopDrag(event) {
      this.mousehasDown = false
      let theTimeOut = setTimeout(() => {
        this.dragging = false
        clearTimeout(theTimeOut)
      }, 0);
    },
    handleMask() {
      console.log('这里是点击事件');
  },
};
</script>

<style>
.count {
  color: red;
}
</style>