如何结合VueUse useDraggable与SVG及v-for实现多元素拖拽?
问题
我希望用VueUse的useDraggable操作SVG组件,通过设置SVG的位置属性(而非样式)来移动元素。目前红色圆形已能正常拖拽,但v-for生成的多个蓝色圆形无法拖拽。想请教:
- 如何组织
useDraggable针对v-for多元素的输出? - 能否把类似红色圆形的{x,y}输出存入统一数据结构供模板使用?
- 或者怎么让我给出的示例方案生效?(不确定模板引用该怎么处理)
解决方案
你的示例核心问题在于模板引用的写法错误,以及useDraggable的初始化时机不对(组件挂载前DOM元素还未生成,ref值为null)。以下是修正后的实现方案:
关键要点
- v-for循环中,SVG元素的ref直接绑定到数组,Vue会自动为每个元素填充对应的DOM引用,无需手动创建
circRefs数组。 - 必须在
onMounted钩子中初始化useDraggable,确保DOM元素已挂载,ref能获取到实际元素。 - 每个蓝色圆形的位置数据直接存在
circs数组的对象中,通过useDraggable的onMove回调实时更新。
完整代码
<script setup> import { useDraggable } from '@vueuse/core' import { ref, reactive, onMounted } from 'vue'; // 蓝色圆形数据 const circs = reactive([]); for (let i = 0; i < 3; i++) { circs.push(reactive({ x: 10 + i*50, y: 10, r: 10 })); } // 用于存储v-for生成的DOM引用,Vue会自动填充 const circRefs = ref([]); // 红色圆形数据 const redCirc = reactive({ x: 40, y: 100, r: 10 }); const redCircRef = ref(null); onMounted(() => { // 初始化蓝色圆形的拖拽 circs.forEach((circ, index) => { const el = circRefs.value[index]; if (el) { useDraggable(el, { initialValue: { x: circ.x, y: circ.y }, onMove: ({ x, y }) => { circ.x = x; circ.y = y; }, }); } }); // 初始化红色圆形的拖拽 useDraggable(redCircRef, { initialValue: { x: redCirc.x, y: redCirc.y }, onMove: ({ x, y }) => { redCirc.x = x; redCirc.y = y; }, }); }); </script> <template> <svg width="400" height="200"> <!-- v-for生成的蓝色圆形 --> <circle v-for="(circ, index) in circs" :key="index" :cx="circ.x" :cy="circ.y" :r="circ.r" fill="blue" ref="circRefs" /> <!-- 红色圆形 --> <circle :cx="redCirc.x" :cy="redCirc.y" :r="redCirc.r" fill="red" ref="redCircRef" /> </svg> </template>
补充说明
- 红色圆形的写法也可以统一到
circs数组中,进一步简化代码,无需单独处理。 useDraggable的onMove回调接收的参数是包含x、y的对象,解构使用更清晰。- 给SVG设置固定宽高,避免拖拽时元素超出可视范围。
内容的提问来源于stack exchange,提问作者eveames
相关产品推荐
相关产品推荐

