react-grid-layout 柵格佈局

前言

最近接觸了一個 react-grid-layout 柵格佈局系統,在使用過程當中發現它的功能不少,可是對於其中的屬性的使用和事件有不少不理解的地方,因此這裏概括(翻譯)一下它的屬性及用途css

react-grid-layout

React-Grid-Layout 是隻提供給 React 組件而且不須要使用 JQuery 的柵格佈局系統,相似的像:Packery Gridster,但 RGL 是響應式的,而且支持 breakpoints 斷點,用戶能夠自定義設置斷點,也能夠由 RGL 自動生成。來自官網的強大動圖: react

RGL

Grid Layout Props

RGL 支持下面這些屬性:css3

基礎屬性

// 基礎屬性
// 在服務器端設置的初始寬度,除非你使用了 HOC <WidthProvider> 或者其餘相似的組件,那麼 width 屬性是必須的。
width: number,

// 當爲 true 的時候,容器高度自適應以適應內容
autoSize: ?boolean = true,

// 將當前佈局分爲多少列
cols: ?number = 12|{},

// 屬性值爲標籤的 css 選擇器,被標記後標籤就不可拖動了
// 好比說:draggableCancel:'.MyNonDraggableAreaClassName'
draggableCancel: ?string = '',

// 屬性值爲標籤的 css 選擇器,被標記後標籤就能夠被拖動
// 好比說: draggableHandle:'.MyDragHandleClassName'
draggableHandle: ?string = '',

// 爲 true 時,會在豎直方向上緊湊排列
verticalCompact: ?boolean = true,

// 緊湊排列的方向
compactType: ?('vertical' | 'horizontal') = 'vertical';

// layouts 屬性值是由這樣格式{x: number, y: number, w: number, h: number}的對象組成的數組
// 須要注意的是,layout在數組中的下標必須和他們做用的組件的 key 值匹配
// 若是但願在組件中使用自定義的 key 值,那麼你能夠在 layout 中指定那個 key 值
// 最後這個對象數組可能像是這樣: {i: string, x: number, y: number, w: number, h: number}
// 也能夠在子組件中單獨設置
layout: ?array = null, 

// 每一個包含塊之間 margin:[x,y] 單位爲 px
margin: ?[number, number] = [10, 10],

//包含塊內部的 padding:[x,y] 單位爲 px
// Padding inside the container [x, y] in px
containerPadding: ?[number, number] = margin,

// 每行的靜態高度,可是若是須要的話你能夠基於 breakpoints 來改變它,
rowHeight: ?number = 150,

// droping 元素的配置,它是一個"虛擬的"元素,當您從外部拖動某個元素時,它會出現
// 它能夠經過傳遞特定參數被改變:
// i - 元素的 id
// w - 元素的寬度
// h - 元素的高度
droppingItem?: { i: string, w: number, h: number }

//
// Flags
//
isDraggable: ?boolean = true,
isResizable: ?boolean = true,
// 使用css3的translate() 代替定位中的 top 和 left,能使繪製過程的性能提高 6 倍
useCSSTransforms: ?boolean = true,
// 若是父節點:ResponsiveReactGridLayout 或者 ReactGridLayout 有 transform: scale(n) 的 css 屬性
// 咱們應該設置比例係數,以免在拖動的過程當中 render artefacts
transformScale: ?number = 1,

// 若是設置true,在拖拽過程中,被拖拽的組件不會改變位置
preventCollision: ?boolean = false;

// 若是設置爲 true,可拖動的元素(帶有 draggable={true} 屬性)能夠在網格上被拖動,他會引起 "onDrop" 回調函數,位置信息和事件對象 做爲參數會被傳到回調函數中,

// 注意:假如使用的是 Firefox 你應該添加 onDragStart={e => e.dataTransfer.setData('text/plain', '')} 屬性和 draggable={true},不然這個特性不會正確的工做
// Firefox 需 要onDragStart 屬性來進行拖放初始化
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=568313
isDroppable: ?boolean = false

//
// Callbacks
//

// 用來保存佈局的回調,每次 drag 或者 resize 結束以後返回當前的佈局
onLayoutChange: (layout: Layout) => void,

//下面全部的回調都有這些參數(layout, oldItem, newItem, placeholder, e, element)
//開始和結束的回調函數中參數:placeholder爲undefined
//
type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem,
                     placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void;


onDragStart: ItemCallback,
onDrag: ItemCallback,
onDragStop: ItemCallback,
onResizeStart: ItemCallback,
onResize: ItemCallback,
onResizeStop: ItemCallback,
onDrop: (elemParams: { x: number, y: number, e: Event }) => void
複製代碼

響應式柵格佈局屬性

響應式柵格佈局是能夠被使用的,它支持👆除 layout 以外全部的基本屬性,新屬性和改變的部分以下:git

// 斷點名是任意的,但必須與cols和layouts對象匹配。
breakpoints: ?Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0},

// 針對 cols 的斷點
cols: ?Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2},

// 固定間隔或者響應式間隔 e.g.[10,10]| `{lg: [10, 10], md: [10, 10], ...}.
margin: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}


// 同上,固定內邊距或者響應式內邊距:e.g. [10,10]|`{lg: [10, 10], md: [10, 10], ...}
containerPadding: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}


// 由斷點查找的 layouts 對象 e.g. {lg: Layout, md: Layout, ...}
layouts: {[key: $Keys<breakpoints>]: Layout}

//
// Callbacks
//

onBreakpointChange: (newBreakpoint: string, newCols: number) => void,

onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keys<breakpoints>]: Layout}) => void,

// 當頁面寬度變化時的回調,這樣你就能夠根據須要修改 layout 啦
onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void;
複製代碼

柵格元素的屬性

請注意,若是提供了一個網格項,但不完整(缺乏x、y、w或h中的一個)的時候將拋出一個錯誤,以便您能夠更正佈局。github

若是沒有爲網格項提供屬性,那麼將生成一個寬度和高度爲1的屬性。數組

您能夠爲每一個維度設置最小值和最大值。這是用來調整大小的;固然,若是禁用了調整大小的功能,則不會產生任何影響。若是你的最小值和最大值互相重疊,或者你的初始尺寸超出範圍將會拋出錯誤。服務器

任何直接定義在中的屬性都將優先於全局設置選項。例如,若是佈局的屬性是isDraggable: false,可是網格項的道具是isDraggable: true,那麼這個項目就是draggable,即便這個項目被標記爲static: true。ide

{

  // 組件的 key 值
  i: string,

  // 這些都是網格單元,而不是像素
  x: number, // 佔幾列
  y: number, // rowHeight 的倍數
  w: number, // 同 x 計算方法
  h: number, // 同 y 計算方法
  minW: ?number = 0,
  maxW: ?number = Infinity,
  minH: ?number = 0,
  maxH: ?number = Infinity,

  // 爲 true 的時候至關於設置 "isDraggable: false, isResizable: false"
  static: ?boolean = false,
  // 爲 false 的時候,不能被拖動,覆蓋掉 static 屬性
  isDraggable: ?boolean = true,
  // 爲 false 的時候,不能從新設置大小,覆蓋掉 static 屬性
  isResizable: ?boolean = true
}
複製代碼

使用

組件的選取

非響應式直接引用 GridLayout 組件,以下:函數

import GridLayout from 'react-grid-layout';
複製代碼

GridLayout 不支持cols、layouts 等支持基於斷點調整值的屬性的屬性值爲斷點調整的對象(eg:{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}),強行使用會使頁面展現效果與預想的不一致,也就是出錯了,當想使用響應式的佈局的時候提倡使用下面的組件。佈局

響應式的使用方法:

當使用響應式模式時,您應該使 layouts 屬性值至少提供一個斷點下的佈局,而且暫時不支持爲單個 grid-item 設置斷點佈局。

一、使用 ResponsiveGridLayout 組件

import { Responsive as ResponsiveGridLayout } from 'react-grid-layout';
複製代碼

二、使用 WidthProvider 函數包裝後的組件 <ResponsiveGridLayout> 和 <ReactGridLayout> 組件在拖動事件中用 width 去計算位置,更簡單的狀況下可使用專用的 WidthProvider 組件能夠在初始化(initialization)和 resize 事件中自動計算寬度

import { Responsive, WidthProvider } from 'react-grid-layout';

const ResponsiveGridLayout = WidthProvider(Responsive);
複製代碼

斷點的使用

上面提到的不少屬性,那些屬性值能夠爲對象的屬性都支持根據斷點來控制元素的佈局,好比說:cols、layouts、containerPadding、margin,它們的使用方法基本一致,以cols 和 margin 爲例:

import React from "react";
import {WidthProvider, Responsive} from 'react-grid-layout';

const ResponsiveGridLayout = WidthProvider(Responsive);
export default class MyFirstGrid extends React.Component {
  render() {
    const layout = [
      {i: 'a', x: 0, y: 0, w: 1, h: 2, static: true},
      {i: 'b', x: 1, y: 0, w: 2, h: 2, minW: 2, maxW: 4},
      {i: 'c', x: 0, y: 2, w: 1, h: 2}
    ];
    return (
      <ResponsiveGridLayout className="layout" layouts={{lg:layout} } rowHeight={30} breakpoints={{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}} margin={{lg: [30,30], md: [20,20], sm: [10,10], xs: [5,5]}} > <div key="a" style={{"background": "red"}}>a</div> <div key="b" style={{"background": "red"}}>b</div> <div key="c" style={{"background": "red"}}>c</div> </ResponsiveGridLayout>
    )
  }
}
複製代碼

效果以下:

能夠看見在斷點處會出現元素寬度和間隔的變化。

複雜一點的,若是想控制元素的位置即每一個元素的 x,y 座標,則可使用 layouts 屬性,針對屏幕不一樣的尺寸更改元素的位置。

一些能夠輔助響應式變化的的事件函數

  • onBreakpointChange 頁面大小從一個斷點區間過渡到另外一個區間的時候觸發,當想響應式的修改其餘原生不支持響應式的屬性的時候(eg: rowHeight)能夠在這裏面修改
  • onLayoutChange 相似於 onBreakpointChange 會在斷點的交界處被觸發,回調函數會傳入當前 layout 和 layouts 的屬性值,能夠在裏面修改對應 key 的佈局
  • onWidthChange 頁面尺寸變化的回調,傳入容器寬度、當前 margin 的值,cols 值、containerPadding 值

巧用緊湊型對齊方式

整個頁面以左上角爲 (0,0)點。

在基本的屬性中注意到有兩個屬性:verticalCompact 和 compactType,分別取值爲 boolean 類型和 string 類型,表示是否採用垂直方向的緊湊對齊或者在什麼方向上緊湊對齊。當 compactType 和 verticalCompact 同時存在的時候,compactType 優先級比 verticalCompact 的優先級高。

使用不一樣的對齊方式會讓頁面的排布有不同的神奇效果: 使用垂直方向上的對齊,當橫座標相同的位置上若是這個元素的前面已經有元素佔據了前面的位置(即縱座標也相同),那麼這個元素排在相同橫座標下最後一個元素的下方,不然排在(x,0)的位置;

特別的是:當水平方向上的空間不足時,誰的 w 值越大誰越靠近 y = 0;

使用水平方向上的對齊,橫縱都座標相同時,從左到右後來者居左,標記爲 static 的除外,會保持在本身的 x 座標上,縱座標相同橫座標不一樣,按照橫座標的數值大小從左到右排列,橫座標相同縱座標不一樣,在這個縱座標前面已經有元素佔據了位置,那麼排在最後一個元素的右邊。

總結

在一些業務場景下,須要使用到這樣的柵格系統來對頁面進行分片再填充,那麼使用 RGL 是比較方便的,但在實踐過程當中多是瞭解的不夠深刻吧,按照github上的例子實踐的時候也出現了一些問題好比即便設置了 isResizable 以後也不能對 grid-item 進行resize,對於他的響應特性、可拖動特性、grid-item 的 resize特性會在之後的實踐中再繼續總結補充。

相關文章
相關標籤/搜索