React-Grid-Layout

简介

React-Grid-Layout(简称为RGL)是一个网格布局系统,可以实现响应式的网格布局,并且支持分割点(breakpoints)的设置,灵活运用可以方便的实现拖拽式组件的实现,就如图下图所展示的:

拖拽组件展示.gif

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
    是否设置边界(若为真且该项可被拖动,则该项只能在网格边界范围内拖动)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容