主要插件Resizable,dnd-kit/core,dnd-kit/sortable,dnd-kit/modifiers
其中官网有列拖拽,主要结合Resizable 实现列拉宽,isResizingRef 很重要防止拖拽相互影响
1.修改TableHeaderCell
const isResizingRef = useRef(false);const TableHeaderCell = props => {const { onResize, width, datagridRef, stretchRef, ...restProps } = props;// 拖拽const dragState = useContext(DragIndexContext);const { attributes, listeners, setNodeRef, isDragging } = useSortable({ id: props.id });const isFixed = props['data-fixed'] && !isResizingRef.current;const style = {...props.style,...(isFixed ? {} : { cursor: 'move' }),...(isDragging ? { position: 'relative', userSelect: 'none' } : {}),...dragActiveStyle(dragState, props.id),};const [offset, setOffset] = useState(0);if (!width) {return <th {...restProps} />;}// 获取要减去的父元素距离左侧的宽度const getPosition = (element) => {let actualLeft = element.offsetLeft;let current = element.offsetParent;while (current !== null) {//当它上面有元素时就继续执行actualLeft += current.offsetLeft;current = current.offsetParent; //继续找父元素}return { x: actualLeft };};// 开始拖拽组织冒泡const handleResizeStart = (e, { size }) => {// console.log(233,e);e.stopPropagation()e.preventDefault()isResizingRef.current = true; // ✅ 开始 resize}const handleResize = (e, { size }) => {// 这里只更新偏移量,数据列表其实并没有伸缩isResizingRef.current = true; // ✅ 开始 resizesetOffset(size.width - width);let parentNodeX = getPosition(datagridRef.current).x;let stretchDom = stretchRef.current;stretchDom.style.display = 'block';stretchDom.style.left = `${e.clientX - parentNodeX + 2}px`;};const handleResizeStop = (...arg) => {// 拖拽结束以后偏移量归零isResizingRef.current = false; // ✅ 结束 resizesetOffset(0);let stretchDom = stretchRef.current;stretchDom.style.display = 'none';stretchDom.style.left = `0px`;// props传进来的事件,在外部是列数据中的onHeaderCell方法提供的事件// console.log(...arg, "arg9");onResize(...arg);};const _ResizableSpan = (<divclassName="react-resizable-handle"// 拖拽层偏移style={{ transform: `translateX(${offset}px)` }}onClick={(e) => {// 取消冒泡,不取消貌似容易触发排序事件e.stopPropagation();e.preventDefault();}}/>);// console.log(isResizingRef.current, "isResizingRef.current");return (<Resizablewidth={width + offset}handle={_ResizableSpan}height={0}// 拖拽事件实时更新onResize={handleResize}// 拖拽结束更新onResizeStop={handleResizeStop}draggableOpts={{ enableUserSelectHack: false }}onResizeStart={handleResizeStart}><th {...restProps}ref={isFixed && !isResizingRef.current ? undefined : setNodeRef}style={style}{...(isFixed && !isResizingRef.current ? {} : attributes)}{...(isFixed && !isResizingRef.current ? {} : listeners)} /></Resizable>);};
2.handleResize 拉宽后处理
// 处理拖拽const handleResize =(key) =>(e, { size }) => {if (size.width < 140) {size.width = 140;}console.log(key, size.width, 9000);setColumns(prev => {const next = prev.map(col => {if (col.dataIndex === key) {return { ...col, width: size.width };}return col;});columRef.current = next;return next;});};
总结来说,样式丑点,目前预测还会碰到未知bug,拉宽的同时会出现回弹之类的bug,慢慢改吧