简介
React-Grid-Layout(简称为RGL)是一个网格布局系统,可以实现响应式的网格布局,并且支持分割点(breakpoints)的设置,灵活运用可以方便的实现拖拽式组件的实现,就如图下图所展示的:
github地址:https://github.com/STRML/react-grid-layout
安装
npm install react-grid-layout
使用时需要引入相关样式
/node_modules/react-grid-layout/css/styles.css
/node_modules/react-resizable/css/styles.css
基本用法
import GridLayout from 'react-grid-layout';
class MyFirstGrid extends React.Component {
render() {
// layout应被定义为一个数组,数组中每一项是一个对象,通过配置对象中的相关属性的值来实现相应的布局和设置
const layout = [
{i: 'a', x: 0, y: 0, w: 1, h: 2, static: true},
{i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4},
{i: 'c', x: 4, y: 0, w: 1, h: 2}
];
return (
<GridLayout className="layout" layout={layout} cols={12} rowHeight={30} width={1200}>
<div key="a">a</div>
<div key="b">b</div>
<div key="c">c</div>
</GridLayout>
)
}
}
上方代码即是一个最简单的用法实现,定义了一个网格布局,其中有a、b、c三个项,其中a因为设置了 static: true,因此它是固定的,不可拖拽和缩放,而b因为设置了 minW: 2 和 maxW: 4,因此它在缩放时的宽度被限定到2到4个单位格之间,而c项只设置了最基本的属性,它可以被自由的拖拽和缩放。
当然,也可以在子组件中来设置相关布局属性:
import GridLayout from 'react-grid-layout';
class MyFirstGrid extends React.Component {
render() {
return (
<GridLayout className="layout" cols={12} rowHeight={30} width={1200}>
<div key="a" data-grid={{x: 0, y: 0, w: 1, h: 2, static: true}}>a</div>
<div key="b" data-grid={{x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4}}>b</div>
<div key="c" data-grid={{x: 4, y: 0, w: 1, h: 2}}>c</div>
</GridLayout>
)
}
}
响应式用法
import { Responsive as ResponsiveGridLayout } from 'react-grid-layout';
class MyResponsiveGrid extends React.Component {
render() {
// {lg: layout1, md: layout2, ...}
const layouts = getLayoutsFromSomewhere();
return (
<ResponsiveGridLayout className="layout" layouts={layouts}
breakpoints={{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}}
cols={{lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}}>
<div key="1">1</div>
<div key="2">2</div>
<div key="3">3</div>
</ResponsiveGridLayout>
)
}
}
breakpoints 设置分割点,cols 设置相应宽度下的总格数,layouts 里面的 layout1 的属性名同基础的 layout 属性配置。
同基本用法相同,依然要设置宽度,否则就会报错,不过RGL中 提供了 WidthProvider HOC ,结合Responsive它就能在初始化和 window resize 时自动确定宽度,下面会介绍到。
结合 WidthProvider使用
import { Responsive, WidthProvider } from 'react-grid-layout';
const ResponsiveGridLayout = WidthProvider(Responsive);
class MyResponsiveGrid extends React.Component {
render() {
// {lg: layout1, md: layout2, ...}
var layouts = getLayoutsFromSomewhere();
return (
<ResponsiveGridLayout className="layout" layouts={layouts}
breakpoints={{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}}
cols={{lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}}>
<div key="1">1</div>
<div key="2">2</div>
<div key="3">3</div>
</ResponsiveGridLayout>
)
}
}
相比于之前的代码,只是多引入了WidthProvider这一个高阶组件,就能实现宽度的自动确定了。当然也可以自己实现一个高阶组件以满足相关复杂逻辑需求。
Grid Layout Props
RGL具有以下的属性:
-
width: number
设置宽度,使用了WidthProvider时不用设置 -
autoSize: ?boolean = true
为真时,容器的高度会自适应内容的高度 -
cols: ?number = 12
布局的列数 -
draggableCancel: ?string = ''
取消拖动时被拖动项的类选择器的名称 -
draggableHandle: ?string = ''
拖动时被拖动项的类选择器的名称 -
verticalCompact: ?boolean = true
为真时,布局在竖直方向上会紧凑排列 -
compactType: ?('vertical' | 'horizontal') = 'vertical'
紧凑排列类型 -
layout: ?array = null
布局数组,每一项是一个对象,形如:{i: string, x: number, y: number, w: number, h: number},如果子组件不设置layout,需要在子组件中设置data-grid
-
margin: ?[number, number] = [10, 10]
项与项之间的间距,单位是px -
containerPadding: ?[number, number] = margin
项的内边距 -
rowHeight: ?number = 150,
行高 -
droppingItem?: { i: string, w: number, h: number }
放置元素的配置(放置元素即是当你拖动某一项时出现的虚拟元素) -
isDraggable: ?boolean = true
是否可拖拽 -
isResizable: ?boolean = true
是否可重置大小 -
isBounded: ?boolean = false
是否设置边界 -
useCSSTransforms: ?boolean = true
是否使用CSS 3 的translate() 来代替 position left/top(可加快渲染速度) -
transformScale: ?number = 1
若ResponsiveReactGridLayout 或者 ReactGridLayout的父组件具有"transform: scale(n)"这一css属性,应该设置这一比例系数以避免拖拽时出现“伪影” -
preventCollision: ?boolean = false
为真时,项在拖动时不会变更位置 -
isDroppable: ?boolean = false
为真时,设置了draggable={true}属性的项可以被放置入其他项 -
resizeHandles: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']
设置重置大小的图标出现的位置,默认是在右下角 -
resizeHandle?: ReactElement<any> | ((resizeHandleAxis: ResizeHandleAxis) => ReactElement<any>)
自定义重置大小组件(即默认出现在右下角的那个小图标,可自定义) -
onLayoutChange: (layout: Layout) => void
布局发生变化的回调函数 -
type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem, placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void
ItemCallback的类型 -
onDragStart: ItemCallback
某一项开始拖动的回调函数 -
onDrag: ItemCallback
某一项正在拖动中的回调函数 -
onDragStop: ItemCallback
某一项停止拖动的回调函数 -
onResizeStart: ItemCallback
某一项开始重置大小的回调函数 -
onResize: ItemCallback
某一项正在重置大小中的回调函数 -
onResizeStop: ItemCallback
某一项停止重置大小的回调函数 -
onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void
某一项所包含的内容中被放置其他元素后的回调函数 -
innerRef: ?React.Ref<"div">
网格的ref
Responsive Grid Layout Props
响应式RGL的特殊属性(除了以下属性的设置有所不同外,其他普通RGL具有的属性都可以设置):
-
breakpoints: ?Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}
一个对象,其中每一项的名称都可以任意设置,只要它的值是数字并且可以与cols 和 layouts中一一对应即可。用以设置响应式布局的分割点 -
cols: ?Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}
一个对象,其中每一项的名称需与breakpoints中一一对应,用以设置布局的列数 -
margin: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}
项与项之间边距的设置 - **containerPadding: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}
**
项的内边距的设置 -
layouts: {[key: $Keys<breakpoints>]: Layout}
布局对象,其中每一项的名称需与breakpoints中一一对应 -
onBreakpointChange: (newBreakpoint: string, newCols: number) => void
breakpoint发生变更时的回调函数 -
onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keys<breakpoints>]: Layout}) => void
布局发生变化的回调函数 -
onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void
宽度发生变化的回调函数
Grid Item Props
网格项的属性:
-
i: string
组件的key -
x: number
横坐标 -
y: number
纵坐标 -
w: number
宽 -
h: number
高 -
minW: ?number = 0
最小宽度 -
maxW: ?number = Infinity
最大宽度 -
minH: ?number = 0
最小高度 -
maxH: ?number = Infinity
最大高度 -
static: ?boolean = false
为真时,项不可拖拽和缩放 -
isDraggable: ?boolean = true
是否可拖拽 -
isResizable: ?boolean = true
是否可缩放 -
resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']
设置重置大小的图标出现的位置,默认是在右下角 -
isBounded: ?boolean = false
是否设置边界(若为真且该项可被拖动,则该项只能在网格边界范围内拖动)