如何在React中实现两列垂直列表的配对连线功能?
两列垂直列表配对连线实现方案
下面提供几种可行的实现方案,适配不同场景需求:
一、基础CSS连线方案(固定布局场景)
适合列表项高度固定、布局规整的情况,利用绝对定位的线条元素实现连线。
实现代码
<div class="pair-container"> <div class="list-column left-list"> <div class="list-item">Apple</div> <div class="list-item">Banana</div> <div class="list-item">Grapes</div> <div class="list-item">Orange</div> </div> <div class="list-column right-list"> <div class="list-item">Red</div> <div class="list-item">Yellow</div> <div class="list-item">Purple</div> <div class="list-item">Orange</div> </div> <!-- 连线元素 --> <div class="connection-line" style="top: 25%"></div> <div class="connection-line" style="top: 45%"></div> <div class="connection-line" style="top: 65%"></div> <div class="connection-line" style="top: 85%"></div> </div>
.pair-container { display: flex; justify-content: space-between; position: relative; width: 600px; margin: 0 auto; padding: 20px; } .list-column { width: 45%; } .list-item { padding: 12px; margin: 10px 0; background: #f0f0f0; border-radius: 4px; } .connection-line { position: absolute; left: 50%; transform: translateX(-50%); width: 2px; height: calc(100% / 4 - 10px); background: #2196f3; }
二、React组件化实现(动态数据场景)
结合你提供的React状态数据,通过组件渲染动态生成列表和连线,支持数据更新。
实现代码
import { useRef, useEffect, useState } from 'react'; const PairConnector = ({ pairs }) => { const leftItemsRef = useRef([]); const rightItemsRef = useRef([]); const [lines, setLines] = useState([]); // 计算连线坐标 useEffect(() => { const newLines = pairs.map((_, index) => { const leftItem = leftItemsRef.current[index]; const rightItem = rightItemsRef.current[index]; if (!leftItem || !rightItem) return null; const leftRect = leftItem.getBoundingClientRect(); const rightRect = rightItem.getBoundingClientRect(); const containerRect = leftItem.parentElement.parentElement.getBoundingClientRect(); return { x1: leftRect.right - containerRect.left, y1: leftRect.top + leftRect.height / 2 - containerRect.top, x2: rightRect.left - containerRect.left, y2: rightRect.top + rightRect.height / 2 - containerRect.top, }; }).filter(Boolean); setLines(newLines); }, [pairs]); return ( <div style={{ display: 'flex', justifyContent: 'space-between', position: 'relative', width: '600px', margin: '0 auto', padding: '20px' }}> {/* SVG 连线层 */} <svg style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', pointerEvents: 'none' }} > {lines.map((line, idx) => ( <line key={idx} x1={line.x1} y1={line.y1} x2={line.x2} y2={line.y2} stroke="#2196f3" strokeWidth="2" /> ))} </svg> {/* 左列表 */} <div style={{ width: '45%' }}> {pairs.map((item, idx) => ( <div key={item.id} ref={el => leftItemsRef.current[idx] = el} style={{ padding: '12px', margin: '10px 0', background: '#f0f0f0', borderRadius: '4px' }} > {item.left} </div> ))} </div> {/* 右列表 */} <div style={{ width: '45%' }}> {pairs.map((item, idx) => ( <div key={item.id} ref={el => rightItemsRef.current[idx] = el} style={{ padding: '12px', margin: '10px 0', background: '#f0f0f0', borderRadius: '4px' }} > {item.right} </div> ))} </div> </div> ); }; // 使用组件 const App = () => { const [pairs, setPairs] = useState([ { id: 1, left: "Apple", right: "Red" }, { id: 2, left: "Banana", right: "Yellow" }, { id: 3, left: "Grapes", right: "Purple" }, { id: 4, left: "Orange", right: "Orange" }, ]); return <PairConnector pairs={pairs} />; }; export default App;
三、SVG精准连线方案(响应式/动态高度场景)
如果列表项高度不固定或需要响应式布局,SVG是最优选择,它能精准计算元素位置生成连线,且支持缩放适配。
核心思路是通过getBoundingClientRect()获取每个列表项的位置坐标,动态生成SVG的<line>元素,确保连线始终对齐左右项的中心。
关键优势
- 适配动态高度的列表项
- 支持响应式布局,窗口大小变化时可重新计算坐标
- 连线样式可灵活定制(虚线、颜色、粗细等)
内容的提问来源于stack exchange,提问作者mitu1234
相关产品推荐
相关产品推荐

