大概是想要这么个效果(只能拖拽中间的线条 拖动其他无效):
怎么实现这个效果呢?原生js中已经提供了相应的api:onmousedown(鼠标按下事件)、onmousemove(鼠标按下后元素移动事件)、onmouseup(松开鼠标事件),快忘记的同学正好可以熟悉巩固一波。
这无非就是一个计算, 通过ref拿到父容器宽度和左侧右侧的子容器宽度,移动事件中计算左侧容器宽度和右侧容器宽度。右侧width = 父容器width - 左侧容器width;
以下是组件核心代码:
import React, { useRef, useEffect, useCallback } from 'react'
import './draggleLayout.less';
const drag = ({ leftDom: ref1, rightDom: ref2, contentDom }, draggleLineDom) => {
const _ref1 = ref1;
const _ref2 = ref2;
draggleLineDom.onmousedown = (e) => {
let _e = e;
const dir = 'horizontal'; // 设置好方向 可通过变量控制默认水平方向 horizontal | vertical
const firstX = _e.clientX; // 获取第一次点击的横坐标
const width = ref2.offsetWidth; // 获取到元素的宽度
// 移动过程中对左右元素宽度计算赋值
document.onmousemove = (_event) => {
_e = _event;
// 可扩展上下拖动等
switch (dir) {
case 'horizontal':
_ref1.style.width = `${contentDom.offsetWidth - width + (_e.clientX - firstX)}px`;
_ref2.style.width = `${width - (_e.clientX - firstX)}px`;
break;
default:
break;
}
};
// 在左侧和右侧元素父容器上绑定松开鼠标解绑拖拽事件
contentDom.onmouseup = () => {
document.onmousemove = null;
};
return false;
};
};
export default function DraggleLayout({contentDom, leftDom, rightDom}) {
const draggleLineRef = useRef();
const init = useCallback(drag.bind(null, { leftDom, rightDom, contentDom }),
[leftDom, rightDom, contentDom, draggleLineRef.current]);
useEffect(() => {
// 初始化绑定拖拽事件
init(draggleLineRef.current);
}, []);
return (<div className='draggleLine-wrapper'><div className='draggleLine' ref={draggleLineRef}></div></div>)
}
使用示例:
import React, { useRef, useEffect, useState } from 'react'
import DraggleLayout from './DraggleLayout';
import './demo.less';
export default function Demo() {
const contentRef = useRef();
const leftDomRef = useRef();
const rightDomRef = useRef();
const [init, setInit] = useState(false);
useEffect(() => {
setInit(true);
}, [])
const draggleLayoutProps = {
contentDom: contentRef.current,
leftDom: leftDomRef.current,
rightDom: rightDomRef.current,
};
return (
<div className='content-wrapper' ref={contentRef}>
<div className='left' ref={leftDomRef}>
左侧
</div>
{/* 父组件加载完再加载子组件 从而通过ref拿到父组件的dom节点 */}
{init && <DraggleLayout {...draggleLayoutProps} />}
<div className='right' ref={rightDomRef}>右侧</div>
</div>
)
}