layout 参考文档
https://github.com/react-grid-layout/react-grid-layout#demos
- 最外层的元素要设置 overflow: ‘hidden’,否则拖拽会有滚动条 ```tsx import { useMemo } from ‘react’; import { WidthProvider, Responsive } from ‘react-grid-layout’; import { array, func, number, object, string } from ‘prop-types’; import { merge } from ‘lodash-es’; import cls from ‘classnames’; import ‘react-grid-layout/css/styles.css’; import ‘react-resizable/css/styles.css’;
const layout = [ { i: ‘a’, x: 0, y: 0, w: 4, h: 1, minW: 3 }, { i: ‘b’, x: 4, y: 0, w: 4, h: 1, minW: 3, maxW: 4 }, { i: ‘c’, x: 8, y: 0, w: 4, h: 1, minW: 3 }, { i: ‘d’, x: 0, y: 1, w: 4, h: 1, minW: 3 }, { i: ‘e’, x: 4, y: 1, w: 4, h: 1, minW: 3 }, ];
// 大屏幕 12列,小屏幕 6列,手机端一列 const defaultCols = { lg: 12, md: 12, sm: 6, xs: 3, xxs: 1 };
ReactGridLayout.propTypes = { dataSource: array.isRequired, onLayoutChange: func.isRequired, gutter: array, rowHeight: number, cols: object, className: string, }; ReactGridLayout.defaultProps = { gutter: [16, 24], rowHeight: 80, };
function ReactGridLayout(props) { const { rowHeight } = props;
const GridLayout = useMemo(() => WidthProvider(Responsive), []);
return (
export default ReactGridLayout;
- WidthProvider 只监听窗口'resize'事件- Response 响应模式下,该属性提供至少一个断点 layouts- Size响应式 [https://github.com/ctrlplusb/react-sizeme](https://github.com/ctrlplusb/react-sizeme)- draggableHandle=".head-title" 只能拖拽的元素- isBounded 只能在 grid里面拖拽<a name="pk7ip"></a>### rowHeight实际像素高度 = (rowHeight * h) + marginH * (h - 1)- 例如,rowHeight={80}, margin={[24, 24]},实际元素的高度 = (80 * 3) + 24 * (3-1) = 288- 宽度会根据多少列,自动计算- { i: 'a', x: 0, y: 0, w: 4, h: 1, minW: 3 },<a name="iNQSI"></a>## layout布局```jsxconst layout = [{i: 'a', // 组件key值,必须是唯一的x: 0, // 组件在x轴坐标,占多少列y: 0, // 组件在y轴坐标,w: 4, // width 宽度,占据多少列宽h: 3, // height 高度,3的意思是 rowHeight 的倍数; 3 * rowHeight// minW: 2, // 最小宽度},{ i: 'b', x: 4, y: 0, w: 4, h: 3 },{ i: 'c', x: 8, y: 0, w: 4, h: 3 },{ i: 'd', x: 0, y: 1, w: 4, h: 3 },{ i: 'e', x: 4, y: 1, w: 4, h: 3 },];
- i 与组件 key相对应的 key
- static,固定布局,不可以拖拽
- static: true,以下都为 isDraggable: false, isResizable: false
- resizeHandles 拖拽手柄,默认只显示右下角手柄
gridItem 属性配置
https://github.com/react-grid-layout/react-grid-layout#grid-item-props
grid配置项要完整,例如:缺少其中一项x, y, w, or h,则会抛出错误
可以设置每个 grid维度的最小值 minH, minW 和最大值 maxH, maxW
{// A string corresponding to the component keyi: string,// These are all in grid units, not pixelsx: number,y: number,w: number,h: number,minW: ?number = 0,maxW: ?number = Infinity,minH: ?number = 0,maxH: ?number = Infinity,// If true, equal to `isDraggable: false, isResizable: false`.static: ?boolean = false,// If false, will not be draggable. Overrides `static`.isDraggable: ?boolean = true,// If false, will not be resizable. Overrides `static`.isResizable: ?boolean = true,// By default, a handle is only shown on the bottom-right (southeast) corner.// Note that resizing from the top or left is generally not intuitive.resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']// If true and draggable, item will be moved only within grid.isBounded: ?boolean = false}
data-grid
import { useMemo } from 'react';import { WidthProvider, Responsive } from 'react-grid-layout';import { array, func, number, object, string } from 'prop-types';import { merge } from 'lodash-es';import cls from 'classnames';import 'react-grid-layout/css/styles.css';import 'react-resizable/css/styles.css';const dataSource = [{ label: "Table", value: 1 },{ label: "List", value: 2 },{ label: "Card", value: 3 },{ label: "Chart", value: 4 },{ label: "Topo", value: 5 }];const defaultCols = { lg: 12, md: 12, sm: 6, xs: 3, xxs: 1 };ReactGridLayout.propTypes = {dataSource: array.isRequired,onLayoutChange: func.isRequired,gutter: array,rowHeight: number,cols: object,className: string,};ReactGridLayout.defaultProps = {gutter: [16, 24],rowHeight: 80,};function ReactGridLayout(props) {const {rowHeight} = props;const GridLayout = useMemo(() => WidthProvider(Responsive), []);// 性能更好的子节点渲染const children = useMemo(() => {return dataSource.map((item, index) => {const grid = {x: (index % 3) * 4, // 组件在x轴坐标y: Math.floor(index / 3),w: 4,h: 3,minW: 2,// maxW: 12,isBounded: true};return (<divkey={index}data-grid={grid}>{item.label}</div>);});}, [dataSource]);const onLayoutChange(layout) {setState(layout);// localStorage.setItem(KEY, JSON.stringify(layout));}return (<GridLayoutclassName={cls('__react-grid-layout__', className)}// 响应式布局断点// layouts={{ lg: layout, md: layout, sm: layout }}// layout={layout}cols={merge(defaultCols, cols)}breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}rowHeight={rowHeight}margin={[24, 24]}containerPadding={[0, 0]}resizeHandles={['ne', 'se']}onLayoutChange={onLayoutChange}>{children}</GridLayout>)}export default ReactGridLayout;
自定义 GridItem
需要将 style、className、onMouseDown、onMouseUp转发 onTouchEnd到同一个 DOM 节点
const CustomGridItem = React.forwardRef((props, ref) => {const {style,className,onMouseDown,onMouseUp,onTouchEnd,children,...rest} = props;return (<divstyle={{...style}}className={className}ref={ref}onMouseDown={onMouseDown}onMouseUp={onMouseUp}onTouchEnd={onTouchEnd}>{/* Make sure to include children to add resizable handle */}{children}</div>);})
draggableHandle 自定义可拖动手柄也需要透传以上属性
