vue实现列表连线
Vue 实现列表连线
在 Vue 中实现列表连线功能,可以通过多种方式完成,以下是几种常见的方法:
使用 SVG 绘制连线
SVG 是一种矢量图形格式,适合用于绘制复杂的连线效果。可以通过动态计算列表项的位置,然后使用 SVG 绘制连线。

<template>
<div>
<div ref="listContainer">
<div v-for="(item, index) in items" :key="index" class="list-item" ref="listItems">
{{ item }}
</div>
</div>
<svg ref="svg" class="connector">
<path v-for="(path, index) in paths" :key="index" :d="path" stroke="black" fill="none" />
</svg>
</div>
</template>
<script>
export default {
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
paths: []
};
},
mounted() {
this.updatePaths();
},
methods: {
updatePaths() {
const items = this.$refs.listItems;
const paths = [];
for (let i = 0; i < items.length - 1; i++) {
const rect1 = items[i].getBoundingClientRect();
const rect2 = items[i + 1].getBoundingClientRect();
const x1 = rect1.left + rect1.width / 2;
const y1 = rect1.bottom;
const x2 = rect2.left + rect2.width / 2;
const y2 = rect2.top;
paths.push(`M ${x1} ${y1} L ${x2} ${y2}`);
}
this.paths = paths;
}
}
};
</script>
<style>
.list-item {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
position: relative;
}
.connector {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
</style>
使用 CSS 伪元素和边框
如果连线效果较为简单,可以通过 CSS 伪元素和边框实现。这种方法适用于垂直或水平排列的列表。

<template>
<div class="list-container">
<div v-for="(item, index) in items" :key="index" class="list-item">
{{ item }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4']
};
}
};
</script>
<style>
.list-container {
position: relative;
}
.list-item {
position: relative;
padding: 10px;
margin-left: 20px;
}
.list-item:not(:last-child)::after {
content: '';
position: absolute;
left: -10px;
top: 100%;
height: 20px;
width: 2px;
background: black;
}
</style>
使用 Canvas 绘制连线
Canvas 提供了更灵活的绘图能力,适合需要动态调整或复杂连线的场景。
<template>
<div>
<div ref="listContainer">
<div v-for="(item, index) in items" :key="index" class="list-item" ref="listItems">
{{ item }}
</div>
</div>
<canvas ref="canvas" class="connector"></canvas>
</div>
</template>
<script>
export default {
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4']
};
},
mounted() {
this.drawConnections();
},
methods: {
drawConnections() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const items = this.$refs.listItems;
const container = this.$refs.listContainer;
canvas.width = container.offsetWidth;
canvas.height = container.offsetHeight;
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
for (let i = 0; i < items.length - 1; i++) {
const rect1 = items[i].getBoundingClientRect();
const rect2 = items[i + 1].getBoundingClientRect();
const x1 = rect1.left + rect1.width / 2;
const y1 = rect1.bottom;
const x2 = rect2.left + rect2.width / 2;
const y2 = rect2.top;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
}
}
};
</script>
<style>
.list-item {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
}
.connector {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
</style>
使用第三方库
如果需要更复杂的连线效果,可以考虑使用第三方库,例如 leader-line 或 jsPlumb。
<template>
<div>
<div v-for="(item, index) in items" :key="index" class="list-item" ref="listItems">
{{ item }}
</div>
</div>
</template>
<script>
import LeaderLine from 'leader-line';
export default {
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
lines: []
};
},
mounted() {
this.drawLines();
},
methods: {
drawLines() {
const items = this.$refs.listItems;
for (let i = 0; i < items.length - 1; i++) {
this.lines.push(new LeaderLine(items[i], items[i + 1]));
}
}
},
beforeDestroy() {
this.lines.forEach(line => line.remove());
}
};
</script>
<style>
.list-item {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
}
</style>
以上方法可以根据实际需求选择适合的方案。SVG 和 Canvas 适合自定义连线效果,而第三方库可以快速实现复杂功能。






