主要插件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,慢慢改吧