react实现拖拽调整宽度
实现拖拽调整宽度的基本思路
在React中实现拖拽调整宽度功能,可以通过监听鼠标事件来控制元素的宽度变化。核心是利用onMouseDown、onMouseMove和onMouseUp事件来跟踪拖动操作。
使用useState和useEffect管理状态
定义一个状态变量来存储当前宽度,并通过事件处理函数更新它。useEffect用于添加和清理全局事件监听器。
import React, { useState, useEffect } from 'react';
const ResizableComponent = () => {
const [width, setWidth] = useState(200);
const [isDragging, setIsDragging] = useState(false);
const handleMouseDown = (e) => {
setIsDragging(true);
e.preventDefault(); // 防止文本选中等副作用
};
useEffect(() => {
const handleMouseMove = (e) => {
if (!isDragging) return;
setWidth(e.clientX); // 根据鼠标位置更新宽度
};
const handleMouseUp = () => {
setIsDragging(false);
};
if (isDragging) {
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
}, [isDragging]);
return (
<div style={{ display: 'flex' }}>
<div style={{ width: `${width}px`, border: '1px solid #ccc' }}>
可调整宽度的区域
</div>
<div
style={{ width: '10px', cursor: 'col-resize', background: '#eee' }}
onMouseDown={handleMouseDown}
/>
</div>
);
};
export default ResizableComponent;
优化拖动体验
添加边界检查和拖动限制,避免宽度超出合理范围。可以在handleMouseMove中增加条件判断:
const handleMouseMove = (e) => {
if (!isDragging) return;
const newWidth = e.clientX;
if (newWidth > 100 && newWidth < 500) { // 限制宽度范围
setWidth(newWidth);
}
};
使用自定义Hook封装逻辑
将拖拽逻辑抽象为自定义Hook,提高代码复用性:
const useResizable = (initialWidth, minWidth, maxWidth) => {
const [width, setWidth] = useState(initialWidth);
const [isDragging, setIsDragging] = useState(false);
const handleMouseDown = (e) => {
setIsDragging(true);
e.preventDefault();
};
useEffect(() => {
const handleMouseMove = (e) => {
if (!isDragging) return;
const newWidth = e.clientX;
if (newWidth >= minWidth && newWidth <= maxWidth) {
setWidth(newWidth);
}
};
const handleMouseUp = () => {
setIsDragging(false);
};
if (isDragging) {
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
}, [isDragging, minWidth, maxWidth]);
return { width, handleMouseDown };
};
// 使用示例
const ResizableComponent = () => {
const { width, handleMouseDown } = useResizable(200, 100, 500);
return (
<div style={{ display: 'flex' }}>
<div style={{ width: `${width}px`, border: '1px solid #ccc' }}>
内容区域
</div>
<div
style={{ width: '10px', cursor: 'col-resize', background: '#eee' }}
onMouseDown={handleMouseDown}
/>
</div>
);
};
处理性能问题
频繁的mousemove事件可能导致性能问题。可以通过节流(throttle)或防抖(debounce)来优化:
import { throttle } from 'lodash';
// 在useEffect中
const handleMouseMove = throttle((e) => {
if (!isDragging) return;
const newWidth = e.clientX;
if (newWidth >= minWidth && newWidth <= maxWidth) {
setWidth(newWidth);
}
}, 16); // 约60fps
支持垂直拖拽调整高度
类似的方法可以用于调整高度,只需修改事件处理逻辑和样式:
const handleMouseMove = (e) => {
if (!isDragging) return;
const newHeight = e.clientY;
setHeight(newHeight);
};
// 样式调整
<div style={{ height: `${height}px`, position: 'relative' }}>
<div
style={{ height: '10px', cursor: 'row-resize', background: '#eee' }}
onMouseDown={handleMouseDown}
/>
</div>






