如何优化drag事件

使用vue-grid-layout实现从侧边栏拖拽组件到设计器中,drag事件会再过程中执行多次造成卡顿,当松开鼠标后还会等待drag事件执行结束才会显示组件(用dragend控制显示),现在怎么优化这个drag事件,使用节流行不通,delay 设置多少都一样

<div
                class="box"
                v-for="(item, index) in items.list"
                :key="index"
                @drag="dragThrottle(item)"
                @dragend="dragend(item)"
                draggable="true"
                unselectable="on"
              >

 throttle(fn, delay = 100) {
      let timer = null
      return function () {
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(this, arguments)
            timer = null
          }, delay)
        }
      }
    },
    dragThrottle(item) {
      this.throttle(this.drag(item), 1000)
    },

    drag(item) {
      console.log('drag')
      const parentRect = document.getElementById('custom-design').getBoundingClientRect()
      const mouseInGrid =
        mouseXY.x > parentRect.left &&
        mouseXY.x < parentRect.right &&
        mouseXY.y > parentRect.top &&
        mouseXY.y < parentRect.bottom
      if (mouseInGrid && this.layout.findIndex((item) => item.i === 'drop') === -1) {
        this.layout.push({
          x: (this.layout.length * 2) % (this.colNum || 12),
          y: this.layout.length + (this.colNum || 12),
          w: item.w,
          h: item.h,
          i: 'drop',
        })
      }
      const index = this.layout.findIndex((item) => item.i === 'drop')
      const indexId = Date.now()
      if (index !== -1) {
        try {
          this.$refs.gridlayout.$children[this.layout.length].$refs.item.style.display = 'none'
        } catch {}
        const el = this.$refs.gridlayout.$children[index]
        el.dragging = { top: mouseXY.y - parentRect.top, left: mouseXY.x - parentRect.left }
        const new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left)
        if (mouseInGrid) {
          this.$refs.gridlayout.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, item.h, item.w)
          DragPos.i = indexId
          DragPos.x = this.layout[index].x
          DragPos.y = this.layout[index].y
          DragPos.w = item.w
          DragPos.h = item.h
        }
        if (!mouseInGrid) {
          this.$refs.gridlayout.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, item.h, item.w)
          this.layout = this.layout.filter((obj) => obj.i !== 'drop')
        }
      }
    },

    dragend(item) {
      const parentRect = document.getElementById('custom-design').getBoundingClientRect()
      const mouseInGrid =
        mouseXY.x > parentRect.left &&
        mouseXY.x < parentRect.right &&
        mouseXY.y > parentRect.top &&
        mouseXY.y < parentRect.bottom
      if (mouseInGrid) {
        this.$refs.gridlayout.dragEvent('dragend', 'drop', DragPos.x, DragPos.y, DragPos.h, DragPos.w)
        this.layout = this.layout.filter((obj) => obj.i !== 'drop')
        this.layout.push({
          x: DragPos.x,
          y: DragPos.y,
          w: DragPos.w,
          h: DragPos.h,
          i: DragPos.i,
          type: item.type,
          widgetConfig: item.widgetConfig,
        })
        this.$nextTick(() => {
          this.$refs.gridlayout.dragEvent('dragend', DragPos.i, DragPos.x, DragPos.y, DragPos.h, DragPos.w)
        })
        try {
          this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display = 'block'
        } catch {}
      }

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
您可以尝试使用requestAnimationFrame(RAF)来优化drag事件,以避免在拖动过程中执行太多的计算和渲染。RAF会在下一帧绘制之前执行回调函数,这可以避免在拖动时导致太多的计算和渲染,并提高性能和流畅度。

以下是一个示例代码,展示如何使用requestAnimationFrame来优化drag事件:

dragThrottle(item) {
  let isDragging = false
  let lastTime = 0
  let requestID = null

  const handleDrag = () => {
    const currentTime = Date.now()
    if (currentTime - lastTime > 16) { // 限制每秒执行的次数为60
      lastTime = currentTime
      this.drag(item)
    }

    if (isDragging) {
      requestID = requestAnimationFrame(handleDrag)
    } else {
      cancelAnimationFrame(requestID)
    }
  }

  const dragStartHandler = () => {
    isDragging = true
    handleDrag()
  }

  const dragEndHandler = () => {
    isDragging = false
  }

  this.$el.addEventListener('dragstart', dragStartHandler, false)
  this.$el.addEventListener('dragend', dragEndHandler, false)
},

在这个示例代码中,handleDrag函数使用requestAnimationFrame来限制每秒执行的次数,防止在拖动期间执行太多的计算和渲染。在dragstart事件中,启动handleDrag函数,在dragend事件中停止它。

您可以将这个示例代码适应您的组件和应用程序,以优化您的drag事件并提高性能。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢