MST

星途 面试题库

面试题:Vue键盘与鼠标事件在复杂交互场景下的协同优化

假设有一个复杂的绘图应用基于Vue开发,用户可以通过鼠标进行绘图操作(如按下鼠标左键开始绘制,移动鼠标进行绘制,松开鼠标左键结束绘制),同时可以通过键盘快捷键(如Ctrl + Z撤销上一步操作)。请设计一个合理的事件处理架构,确保在高并发操作下(如快速绘制并频繁撤销),系统依然能保持良好的性能和响应,详细说明事件监听、处理逻辑以及如何进行性能优化,同时给出关键代码示例。
17.6万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

事件监听

  1. 鼠标事件监听:在Vue的模板中,通过@mousedown@mousemove@mouseup指令来监听鼠标的按下、移动和松开事件。
<template>
  <div @mousedown="handleMouseDown" @mousemove="handleMouseMove" @mouseup="handleMouseUp"></div>
</template>
  1. 键盘事件监听:使用@keydown指令来监听键盘事件,并结合event.ctrlKeyevent.key === 'z'判断是否是Ctrl + Z快捷键。
<template>
  <div @keydown="handleKeyDown"></div>
</template>

处理逻辑

  1. 绘图逻辑
    • handleMouseDown中记录起始坐标,并开始一个绘制状态。
    • handleMouseMove在绘制状态下根据当前坐标和起始坐标绘制图形(可以是线条等)。
    • handleMouseUp结束绘制状态,并将绘制的图形保存到一个数组中,用于后续的撤销操作。
export default {
  data() {
    return {
      isDrawing: false,
      startX: 0,
      startY: 0,
      drawings: []
    };
  },
  methods: {
    handleMouseDown(event) {
      this.isDrawing = true;
      this.startX = event.offsetX;
      this.startY = event.offsetY;
    },
    handleMouseMove(event) {
      if (this.isDrawing) {
        // 这里可以调用实际的绘图函数,如drawLine(this.startX, this.startY, event.offsetX, event.offsetY)
      }
    },
    handleMouseUp() {
      this.isDrawing = false;
      // 假设这里有一个函数getCurrentDrawing获取当前绘制的图形
      const drawing = getCurrentDrawing();
      this.drawings.push(drawing);
    }
  }
};
  1. 撤销逻辑
    • handleKeyDown中判断是Ctrl + Z快捷键时,从drawings数组中移除最后一个绘制的图形,并重新绘制画布。
export default {
  methods: {
    handleKeyDown(event) {
      if (event.ctrlKey && event.key === 'z') {
        if (this.drawings.length > 0) {
          this.drawings.pop();
          // 重新绘制画布的函数,如redrawCanvas(this.drawings)
        }
      }
    }
  }
};

性能优化

  1. 防抖与节流
    • 对于@mousemove事件,由于其触发频率很高,可以使用节流(throttle)技术,确保在一定时间间隔内只执行一次绘图逻辑,减少不必要的计算。
    • 例如使用lodashthrottle函数:
import throttle from 'lodash/throttle';
export default {
  data() {
    return {
      // 其他数据...
      throttledHandleMouseMove: null
    };
  },
  created() {
    this.throttledHandleMouseMove = throttle(this.handleMouseMove, 50);
  },
  methods: {
    handleMouseMove(event) {
      if (this.isDrawing) {
        // 实际绘图逻辑
      }
    }
  },
  beforeDestroy() {
    this.throttledHandleMouseMove.cancel();
  }
};
  1. 批量操作
    • 在撤销操作时,不要每次都立即重新绘制整个画布,而是将多个撤销操作合并,在合适的时机一次性重新绘制。可以设置一个队列,当撤销操作触发时,先将操作放入队列,然后在队列达到一定数量或者一定时间间隔后,再统一执行重新绘制操作。
  2. 使用Web Worker(可选)
    • 如果绘图操作非常复杂,占用大量CPU资源,可以考虑使用Web Worker将部分计算密集型任务放到后台线程执行,避免阻塞主线程,提高应用的响应性。

通过上述事件处理架构、处理逻辑以及性能优化措施,可以使复杂的绘图应用在高并发操作下保持良好的性能和响应。