当前位置:首页 > VUE

vue实现鼠标拖动多选

2026-02-22 12:06:31VUE

实现鼠标拖动多选的核心思路

监听鼠标的mousedownmousemovemouseup事件,通过计算鼠标移动轨迹和位置,动态生成一个选择框。检测目标元素是否在选择框范围内,更新选中状态。

基础代码结构

<template>
  <div 
    class="container"
    @mousedown="startDrag"
    @mousemove="onDrag"
    @mouseup="endDrag"
  >
    <div 
      v-for="item in items" 
      :key="item.id"
      class="selectable-item"
      :class="{ selected: selectedItems.includes(item.id) }"
    >
      {{ item.name }}
    </div>
    <div 
      v-if="isDragging"
      class="selection-box"
      :style="selectionBoxStyle"
    />
  </div>
</template>

数据与事件处理

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        // 更多项目...
      ],
      selectedItems: [],
      isDragging: false,
      startPos: { x: 0, y: 0 },
      currentPos: { x: 0, y: 0 }
    }
  },
  computed: {
    selectionBoxStyle() {
      const left = Math.min(this.startPos.x, this.currentPos.x)
      const top = Math.min(this.startPos.y, this.currentPos.y)
      const width = Math.abs(this.currentPos.x - this.startPos.x)
      const height = Math.abs(this.currentPos.y - this.startPos.y)

      return {
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${height}px`
      }
    }
  },
  methods: {
    startDrag(e) {
      this.isDragging = true
      this.startPos = { x: e.clientX, y: e.clientY }
      this.currentPos = { x: e.clientX, y: e.clientY }
    },
    onDrag(e) {
      if (!this.isDragging) return
      this.currentPos = { x: e.clientX, y: e.clientY }
      this.updateSelection()
    },
    endDrag() {
      this.isDragging = false
    }
  }
}
</script>

碰撞检测实现

methods: {
  updateSelection() {
    const selectionBox = {
      left: Math.min(this.startPos.x, this.currentPos.x),
      top: Math.min(this.startPos.y, this.currentPos.y),
      right: Math.max(this.startPos.x, this.currentPos.x),
      bottom: Math.max(this.startPos.y, this.currentPos.y)
    }

    this.selectedItems = []
    const items = document.querySelectorAll('.selectable-item')

    items.forEach(item => {
      const rect = item.getBoundingClientRect()
      const isIntersecting = !(
        selectionBox.right < rect.left || 
        selectionBox.left > rect.right || 
        selectionBox.bottom < rect.top || 
        selectionBox.top > rect.bottom
      )

      if (isIntersecting) {
        const itemId = parseInt(item.dataset.id)
        this.selectedItems.push(itemId)
      }
    })
  }
}

样式优化

<style>
.container {
  position: relative;
  width: 100%;
  height: 100vh;
}

.selectable-item {
  position: absolute;
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
}

.selectable-item.selected {
  background-color: rgba(0, 123, 255, 0.3);
  border-color: #007bff;
}

.selection-box {
  position: absolute;
  background-color: rgba(0, 123, 255, 0.1);
  border: 1px dashed #007bff;
  pointer-events: none;
}
</style>

性能优化建议

使用事件委托减少事件监听器数量,避免在mousemove中频繁操作DOM。可以添加防抖处理减少不必要的计算。

methods: {
  onDrag: _.throttle(function(e) {
    if (!this.isDragging) return
    this.currentPos = { x: e.clientX, y: e.clientY }
    this.updateSelection()
  }, 50)
}

完整组件示例

将上述代码整合为一个完整组件,确保所有功能协同工作。注意处理边界情况,如滚动容器、元素重叠等场景。

vue实现鼠标拖动多选

标签: 鼠标拖动
分享给朋友:

相关文章

vue如何实现拖动

vue如何实现拖动

Vue 实现拖动的几种方法 使用 HTML5 原生拖放 API HTML5 提供了原生的拖放 API,通过 draggable 属性和相关事件实现拖动功能。 <template> &…

vue 实现拖动

vue 实现拖动

实现拖动的核心方法 在Vue中实现拖动功能可以通过HTML5的拖放API或第三方库如vuedraggable。以下是两种常见方案的实现细节。 使用HTML5原生拖放API HTML5提供了drag…

vue实现组件拖动

vue实现组件拖动

Vue 实现组件拖动的几种方法 使用 HTML5 拖放 API HTML5 原生提供了拖放 API,可以通过 draggable 属性实现基础拖拽功能。在 Vue 中可以通过事件绑定实现交互逻辑。…

Vue实现鼠标悬浮

Vue实现鼠标悬浮

鼠标悬浮效果实现方法 在Vue中实现鼠标悬浮效果可以通过多种方式完成,以下是几种常见方法: 使用v-on指令绑定事件 通过@mouseenter和@mouseleave事件可以实现悬浮效果 &…

vue实现拖动滑动

vue实现拖动滑动

Vue 实现拖动滑动 使用原生 HTML5 拖放 API 在 Vue 中可以通过 @dragstart、@dragover、@drop 等事件实现基础的拖放功能。以下是一个简单的拖放示例: <…

vue 实现拖动效果

vue 实现拖动效果

使用 Vue 实现拖动效果 Vue 提供了多种方式实现拖动效果,可以通过原生 HTML5 的拖放 API,也可以使用第三方库如 vuedraggable。以下是两种常见的方法: 使用 HTML5 拖…