You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 11:41:12