React组件顶部边框拖拽调整大小实现方案咨询
Hey there! 很高兴你已经有了用state管理高度的思路,这完全踩中了React的核心思想——咱们就沿着这个方向走,完全不用依赖jQuery或者直接操作DOM,纯React原生就能实现这个拖拽调整高度的功能。
实现思路与代码示例
核心逻辑是通过监听鼠标的mousedown、mousemove、mouseup事件计算高度变化,全程用React的state驱动视图更新,完全贴合React的数据驱动理念。
1. 组件基础结构与状态定义
先搭建抽屉的基本结构,把高度存在state中,同时给顶部拖拽手柄绑定mousedown事件:
import { useState, useRef, useEffect } from 'react'; const DraggableDrawer = () => { // 抽屉初始高度,可根据需求调整 const [drawerHeight, setDrawerHeight] = useState(400); // 记录拖拽开始时的鼠标Y坐标和抽屉初始高度 const dragStartInfo = useRef({ startY: 0, startHeight: 0 }); // 标记是否处于拖拽状态 const isDragging = useRef(false); // 鼠标按下时触发,初始化拖拽信息 const handleDragStart = (e) => { isDragging.current = true; dragStartInfo.current = { startY: e.clientY, startHeight: drawerHeight }; // 阻止默认行为,避免页面滚动干扰拖拽 e.preventDefault(); }; return ( <div className="drawer-container" style={{ height: `${drawerHeight}px` }}> {/* 顶部拖拽手柄 */} <div className="drawer-drag-handle" onMouseDown={handleDragStart} > <span>拖拽调整高度</span> </div> {/* 抽屉内容区域 */} <div className="drawer-content"> 这里是抽屉的内容区域... </div> </div> ); }; export default DraggableDrawer;
2. 全局监听拖拽过程
因为拖拽时鼠标可能移出抽屉区域,所以要在window上监听mousemove和mouseup事件,确保拖拽过程连贯:
useEffect(() => { const handleDragMove = (e) => { if (!isDragging.current) return; // 计算鼠标移动距离:向上拖增加高度,向下拖减少高度 const deltaY = dragStartInfo.current.startY - e.clientY; // 限制高度范围,避免抽屉过小或过大 const newHeight = Math.max(200, Math.min(800, dragStartInfo.current.startHeight + deltaY)); setDrawerHeight(newHeight); }; const handleDragEnd = () => { isDragging.current = false; }; // 添加全局事件监听 window.addEventListener('mousemove', handleDragMove); window.addEventListener('mouseup', handleDragEnd); // 组件卸载时移除监听,避免内存泄漏 return () => { window.removeEventListener('mousemove', handleDragMove); window.removeEventListener('mouseup', handleDragEnd); }; }, [drawerHeight]);
3. 样式优化(可选但建议)
给拖拽手柄添加明显样式,让用户清晰感知可交互:
.drawer-container { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 1px solid #eee; box-shadow: 0 -2px 10px rgba(0,0,0,0.1); overflow: hidden; } .drawer-drag-handle { height: 30px; background: #f5f5f5; display: flex; align-items: center; justify-content: center; cursor: ns-resize; /* 鼠标显示上下箭头样式 */ user-select: none; /* 防止拖拽时选中文本 */ } .drawer-content { height: calc(100% - 30px); overflow-y: auto; padding: 16px; }
方案优势
- 完全遵循React数据驱动视图原则:所有高度变化都通过更新state触发组件重渲染,没有直接操作DOM样式。
- 无第三方依赖:只用React原生Hooks实现,不需要引入jQuery或其他拖拽库。
- 体验完善:通过全局事件监听保证拖拽连贯性,添加高度边界限制避免异常情况,组件卸载时清理事件防止内存泄漏。
如果是类组件写法,逻辑完全一致:把状态存在this.state中,事件处理函数写为类方法,在componentDidMount添加全局监听,componentWillUnmount移除监听即可。
内容的提问来源于stack exchange,提问作者CarCarlo
相关产品推荐
相关产品推荐

