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

在React中不依赖第三方库实现鼠标拖拽调整div大小的方法

纯React实现左右面板拖拽调整宽度方案(无第三方依赖)

1. 实现思路

  • 监听拖拽元素的mousedown事件标记拖拽开始
  • 全局监听mousemove事件计算鼠标水平位移,动态调整左侧面板宽度
  • 全局监听mouseup事件结束拖拽状态
  • 通过CSS控制拖拽条固定在右侧面板左边缘,替代原生resize的右下角控件

2. 完整代码实现

React组件代码

import { useState, useRef, useCallback, useEffect } from 'react';
import './ResizablePanel.css';

const ResizablePanel = () => {
  // 左侧面板初始宽度,可根据需求调整
  const [leftWidth, setLeftWidth] = useState(300);
  // 标记是否正在拖拽
  const [isDragging, setIsDragging] = useState(false);
  // 存储拖拽开始时的鼠标X坐标和初始左侧宽度
  const dragStartX = useRef(0);
  const startWidth = useRef(0);

  // 拖拽开始事件
  const handleMouseDown = useCallback((e) => {
    setIsDragging(true);
    dragStartX.current = e.clientX;
    startWidth.current = leftWidth;
    // 拖拽时禁用文本选择,优化体验
    document.body.style.userSelect = 'none';
  }, [leftWidth]);

  // 拖拽中事件
  const handleMouseMove = useCallback((e) => {
    if (!isDragging) return;
    const deltaX = e.clientX - dragStartX.current;
    // 可设置最小宽度避免面板过窄,这里最小设为100px,可自行修改
    const newWidth = Math.max(100, startWidth.current + deltaX);
    setLeftWidth(newWidth);
  }, [isDragging]);

  // 拖拽结束事件
  const handleMouseUp = useCallback(() => {
    setIsDragging(false);
    document.body.style.userSelect = 'auto';
  }, []);

  // 全局监听鼠标移动和抬起事件
  useEffect(() => {
    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);
    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
    };
  }, [handleMouseMove, handleMouseUp]);

  return (
    <div id="container">
      <div id="left_panel" style={{ width: `${leftWidth}px` }}>
        left content!
      </div>
      <div id="right_panel">
        <div id="drag" onMouseDown={handleMouseDown}></div>
        right content!
      </div>
    </div>
  );
};

export default ResizablePanel;

对应CSS代码(ResizablePanel.css)

#container {
  display: flex;
  width: 100%;
  height: 400px; /* 可根据需求调整容器高度 */
  border: 1px solid #eee;
}

#left_panel {
  flex-shrink: 0;
  height: 100%;
  background: #f5f5f5;
  padding: 16px;
  box-sizing: border-box;
}

#right_panel {
  position: relative;
  flex-grow: 1;
  height: 100%;
  padding: 16px;
  box-sizing: border-box;
}

#drag {
  position: absolute;
  left: 0;
  top: 0;
  width: 4px;
  height: 100%;
  background: #ddd;
  cursor: col-resize;
  transition: background 0.2s;
}

#drag:hover {
  background: #1677ff;
}

3. 方案说明

  • 完全基于React原生API和原生JS事件实现,无任何第三方依赖
  • 拖拽条固定在两个面板的分界处,符合你需要的右边框位置需求
  • 内置最小宽度限制,避免拖拽导致面板过窄,可根据需求调整阈值
  • 拖拽过程中禁用全局文本选择,避免误选内容的体验问题

内容的提问来源于stack exchange,提问作者devb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:54:02