原文合集地址如下,有需要的朋友可以关注
本文地址
合集地址
在项目中,设计说想做个面板,其宽度随鼠标拖拽而变化,有最大最小值。基于这个小功能封装一个可拖拽组件,在需要的地方引入即可。
思路
这里只是实现x方向的拖拽,y轴拖拽思路差不多。
既然是鼠标操作,那肯定得监听鼠标事件,当鼠标按下(mouseDown)时,监听mouseMove事件和mouseUp事件,就是鼠标移动和抬起操作。然后计算出鼠标移动的宽度 = 元素现在的x坐标(clientX) - 起始坐标;然后把移动的宽度通过onChange函数返回给父组件,父组件改变自身的宽度。
代码示例
组件代码如下:
import React, { useRef, useState, useEffect } from 'react';
interface DragLineProps {style?: any; // 自定义样式className?: string; // 样式类名onChange: (width: number, height:number) => void; // 宽高变化函数
}const DragLine: React.FC<DragLineProps> = (props) => {const {style, className, onChange } = props;const containerRef = useRef<HTMLDivElement>(null);const [isDragging, setIsDragging] = useState(false);const initialMouseX = useRef(0); // 初始x值const initialMouseY = useRef(0); // 初始Y值useEffect(() => {const handleMouseMove = (event: MouseEvent) => {if (isDragging && containerRef.current) {const deltaX = event.clientX - initialMouseX?.current;const deltaY = event.clientY - initialMouseY?.current;// 调用父组件函数,传回移动的宽度或高度onChange(deltaX, deltaY)}};const handleMouseUp = () => {setIsDragging(false);};// 添加鼠标移动和抬起事件document.addEventListener('mousemove', handleMouseMove);document.addEventListener('mouseup', handleMouseUp);return () => {// 记得清除监听事件document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);};}, [isDragging, initialMouseX, initialMouseY, onChange]);/** 监听鼠标按下事件 改变初始值 **/const handleMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {event.preventDefault();setIsDragging(true);initialMouseX.current = event.clientX;initialMouseY.current = event.clientY;};return (<divref={containerRef}className={className} style={style}onMouseDown={handleMouseDown}/>);};export default DragLine;
使用:
我这里是左侧面板可拖拽宽度,当然也可以是右侧面板,如需上下拖动,可以先定义高度,然后通过子组件调用handleChange传回的offsetY操作即可。
import React, { useState } from 'react';
import DragLine from '../../components/DragBox';
import './style.less';
const maxWidth = 300;
const minWidth = 100;
const App: React.FC = () => {const [width, setWidth] = useState(200);const handleChange = (offsetX: number, offsetY:number) => {const current = offsetX+ width;const newWidth = current > maxWidth ? maxWidth : current < minWidth ? minWidth : current;setWidth(newWidth);};return (<div className='DragWrapperRoot'><div style={{width}} className='dragBox'> 拖拽右侧边框改变盒子大小</div><DragLine onChange={handleChange} className="width-drag" style={{left: width}}/></div>);
};export default App;
less文件:
.DragWrapperRoot{position: relative;display: flex;height: 80%;.dragBox{position: relative;border-right: 1px solid #999;height: 100%;}.width-drag{position: absolute; cursor: ew-resize; // 鼠标悬停双箭头样式top: 0;bottom: 0;width: 10px;background: transparent;}
}
总结
- 创建一个
DragLine
组件,接受一个onChange
函数作为参数,该函数用于接收拖拽宽度的更新。 - 使用
useRef
钩子来获取<div>
容器的引用,以便后续操作。 - 使用
useState
钩子来追踪拖拽状态,通过isDragging
变量表示是否正在拖拽。 - 使用
useEffect
钩子来添加事件监听器,以便在鼠标移动和释放的过程中执行相应的操作。 - 在
handleMouseMove
回调函数中,根据鼠标位置和容器的左边界计算新的宽度和高度,并通过onChange
函数将新的宽度传递给父组件。 - 在
handleMouseUp
回调函数中,将拖拽状态设置为false
,表示拖拽结束。 - 在
handleMouseDown
回调函数中,将拖拽状态设置为true
,表示开始拖拽。 - 将
handleMouseDown
函数绑定到容器的onMouseDown
事件上,以便在鼠标按下时触发拖拽行为。 - 在组件的返回部分,使用
ref
将容器的引用与<div>
元素关联起来。 - 通过添加适当的CSS样式,使得容器显示为竖线,并具有适当的拖拽光标效果。
DragLine`组件的思路是利用事件监听器来捕获鼠标的拖拽行为,计算拖拽宽度,并通过回调函数将更新后的宽度和高度传递给父组件。这样可以实现通过鼠标拖拽来改变容器宽度或者高度的功能。