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 (

a
b
c
d
e
) }

export default ReactGridLayout;

  1. - WidthProvider 只监听窗口'resize'事件
  2. - Response 响应模式下,该属性提供至少一个断点 layouts
  3. - Size响应式 [https://github.com/ctrlplusb/react-sizeme](https://github.com/ctrlplusb/react-sizeme)
  4. - draggableHandle=".head-title" 只能拖拽的元素
  5. - isBounded 只能在 grid里面拖拽
  6. <a name="pk7ip"></a>
  7. ### rowHeight
  8. 实际像素高度 = (rowHeight * h) + marginH * (h - 1)
  9. - 例如,rowHeight={80}, margin={[24, 24]},实际元素的高度 = (80 * 3) + 24 * (3-1) = 288
  10. - 宽度会根据多少列,自动计算
  11. - { i: 'a', x: 0, y: 0, w: 4, h: 1, minW: 3 },
  12. ![image.png](https://cdn.nlark.com/yuque/0/2023/png/112859/1690511562812-1f86a95a-5be3-4130-ad47-5a6aabb03689.png#averageHue=%23c6d8f3&clientId=u30ddcccd-3015-4&from=paste&height=76&id=u31e7c8ae&originHeight=168&originWidth=1408&originalType=binary&ratio=2.200000047683716&rotation=0&showTitle=false&size=99589&status=done&style=none&taskId=u098cda6d-a415-446f-a971-0060ddff073&title=&width=639.9999861283738)
  13. <a name="iNQSI"></a>
  14. ## layout布局
  15. ```jsx
  16. const layout = [
  17. {
  18. i: 'a', // 组件key值,必须是唯一的
  19. x: 0, // 组件在x轴坐标,占多少列
  20. y: 0, // 组件在y轴坐标,
  21. w: 4, // width 宽度,占据多少列宽
  22. h: 3, // height 高度,3的意思是 rowHeight 的倍数; 3 * rowHeight
  23. // minW: 2, // 最小宽度
  24. },
  25. { i: 'b', x: 4, y: 0, w: 4, h: 3 },
  26. { i: 'c', x: 8, y: 0, w: 4, h: 3 },
  27. { i: 'd', x: 0, y: 1, w: 4, h: 3 },
  28. { i: 'e', x: 4, y: 1, w: 4, h: 3 },
  29. ];
  • 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

  1. {
  2. // A string corresponding to the component key
  3. i: string,
  4. // These are all in grid units, not pixels
  5. x: number,
  6. y: number,
  7. w: number,
  8. h: number,
  9. minW: ?number = 0,
  10. maxW: ?number = Infinity,
  11. minH: ?number = 0,
  12. maxH: ?number = Infinity,
  13. // If true, equal to `isDraggable: false, isResizable: false`.
  14. static: ?boolean = false,
  15. // If false, will not be draggable. Overrides `static`.
  16. isDraggable: ?boolean = true,
  17. // If false, will not be resizable. Overrides `static`.
  18. isResizable: ?boolean = true,
  19. // By default, a handle is only shown on the bottom-right (southeast) corner.
  20. // Note that resizing from the top or left is generally not intuitive.
  21. resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']
  22. // If true and draggable, item will be moved only within grid.
  23. isBounded: ?boolean = false
  24. }

data-grid

  1. import { useMemo } from 'react';
  2. import { WidthProvider, Responsive } from 'react-grid-layout';
  3. import { array, func, number, object, string } from 'prop-types';
  4. import { merge } from 'lodash-es';
  5. import cls from 'classnames';
  6. import 'react-grid-layout/css/styles.css';
  7. import 'react-resizable/css/styles.css';
  8. const dataSource = [
  9. { label: "Table", value: 1 },
  10. { label: "List", value: 2 },
  11. { label: "Card", value: 3 },
  12. { label: "Chart", value: 4 },
  13. { label: "Topo", value: 5 }
  14. ];
  15. const defaultCols = { lg: 12, md: 12, sm: 6, xs: 3, xxs: 1 };
  16. ReactGridLayout.propTypes = {
  17. dataSource: array.isRequired,
  18. onLayoutChange: func.isRequired,
  19. gutter: array,
  20. rowHeight: number,
  21. cols: object,
  22. className: string,
  23. };
  24. ReactGridLayout.defaultProps = {
  25. gutter: [16, 24],
  26. rowHeight: 80,
  27. };
  28. function ReactGridLayout(props) {
  29. const {
  30. rowHeight
  31. } = props;
  32. const GridLayout = useMemo(() => WidthProvider(Responsive), []);
  33. // 性能更好的子节点渲染
  34. const children = useMemo(() => {
  35. return dataSource.map((item, index) => {
  36. const grid = {
  37. x: (index % 3) * 4, // 组件在x轴坐标
  38. y: Math.floor(index / 3),
  39. w: 4,
  40. h: 3,
  41. minW: 2,
  42. // maxW: 12,
  43. isBounded: true
  44. };
  45. return (
  46. <div
  47. key={index}
  48. data-grid={grid}
  49. >
  50. {item.label}
  51. </div>
  52. );
  53. });
  54. }, [dataSource]);
  55. const onLayoutChange(layout) {
  56. setState(layout);
  57. // localStorage.setItem(KEY, JSON.stringify(layout));
  58. }
  59. return (
  60. <GridLayout
  61. className={cls('__react-grid-layout__', className)}
  62. // 响应式布局断点
  63. // layouts={{ lg: layout, md: layout, sm: layout }}
  64. // layout={layout}
  65. cols={merge(defaultCols, cols)}
  66. breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
  67. rowHeight={rowHeight}
  68. margin={[24, 24]}
  69. containerPadding={[0, 0]}
  70. resizeHandles={['ne', 'se']}
  71. onLayoutChange={onLayoutChange}
  72. >
  73. {children}
  74. </GridLayout>
  75. )
  76. }
  77. export default ReactGridLayout;

自定义 GridItem

需要将 style、className、onMouseDown、onMouseUp转发 onTouchEnd到同一个 DOM 节点

  1. const CustomGridItem = React.forwardRef((props, ref) => {
  2. const {
  3. style,
  4. className,
  5. onMouseDown,
  6. onMouseUp,
  7. onTouchEnd,
  8. children,
  9. ...rest
  10. } = props;
  11. return (
  12. <div
  13. style={{...style}}
  14. className={className}
  15. ref={ref}
  16. onMouseDown={onMouseDown}
  17. onMouseUp={onMouseUp}
  18. onTouchEnd={onTouchEnd}
  19. >
  20. {/* Make sure to include children to add resizable handle */}
  21. {children}
  22. </div>
  23. );
  24. })

draggableHandle 自定义可拖动手柄也需要透传以上属性

resizeHandles 缩放手柄