基於react-grid-layout實現可視化拖拽

前言

作前端的小夥伴們可能會常常遇到作一個自定義dashboard這樣的需求。 那麼什麼是自定義dashboard呢?自定義dashboard其實就是一個自定義面板,用戶可以在面板上自由的拖拽,新增,刪除組件。組件能夠是各類echarts圖形,也但是各類數據表格。經過各個組件的拖拽組合,從而讓用戶自定義想要看到的面板。css

項目預覽

demo地址前端

源碼地址 react

QQ20190514-131658-HD-compress.gif
組件能夠動態添加,刪除,能夠自由拖拽,縮放。而且縮放後組件內部的echarts圖表也會跟着縮放。

技術架構

  1. 前端框架:React
  2. UI庫:Ant Design
  3. 腳手架:create-react-app
  4. 拖拽插件:react-grid-layout

技術實現

1. 使用npm安裝react-grid-layout包
npm install react-grid-layout
複製代碼
2. 插件聲明及樣式引入

首先,在js文件中引入WidthProvider和Responsive組件,而且實例化響應式拖拽組件。 其次,在css文件中引入插件的樣式。git

import { WidthProvider, Responsive } from "react-grid-layout";
const ResponsiveReactGridLayout = WidthProvider(Responsive);
複製代碼
@import '~react-grid-layout/css/styles.css';
@import '~react-resizable/css/styles.css';
複製代碼
3. Render渲染

在React的render方法中渲染可拖拽佈局。ResponsiveReactGridLayout組件有多個屬性,這裏舉幾個比較重要的說明一下:github

  • cols:定義了響應式佈局劃分紅幾列。
  • rowHeight:響應式佈局中組件的行高。
  • onLayoutChange:當響應式佈局中的組件發生拖拽或者放大縮小時觸發該函數。
<ResponsiveReactGridLayout
    className="layout"
    {...this.props}
    layouts={this.state.layouts}
    onLayoutChange={(layout, layouts) =>
              this.onLayoutChange(layout, layouts)
            }
   >
     {this.generateDOM()}
</ResponsiveReactGridLayout>
複製代碼
4.組件DOM生成

經過generateDOM函數生成佈局中的組件,首先先遍歷組件數組,經過每一個組件的類型判斷生產柱狀圖組件,折線組件,仍是餅圖組件。每一個組件必須定義一個全局惟一的key值。data-grid爲每個組件綁定了其屬性。下面會介紹具體的data-grid屬性。npm

generateDOM = () => {
    return _.map(this.state.widgets, (l, i) => {
      let option;
      if (l.type === 'bar') {
        option = getBarChart();
      }else if (l.type === 'line') {
        option = getLineChart();
      }else if (l.type === 'pie') {
        option = getPieChart();
      }
      let component = (
        <ReactEcharts
          option={option}
          notMerge={true}
          lazyUpdate={true}
          style={{width: '100%',height:'100%'}}
        />
      )
      return (
        <div key={l.i} data-grid={l}>
          <span className='remove' onClick={this.onRemoveItem.bind(this, i)}>x</span>
          {component}
        </div>
      );
    });
  };
複製代碼
5. 經過addItem函數來新增組件。

每一個組件屬性以下:數組

  • x: 組件在x軸座標
  • y: 組件在y軸座標
  • w: 組件寬度
  • h: 組件高度
  • i: 組件key值
addItem(type,widgetId) {
    const addItem = {
      x: (this.state.widgets.length * 2) % (this.state.cols || 12),
      y: Infinity, // puts it at the bottom
      w: 2,
      h: 2,
      i: widgetId || new Date().getTime().toString(),
    };
    this.setState(
      {
        widgets: this.state.widgets.concat({
          ...addItem,
          type,
        }),
      },
    );
  };
複製代碼
6. 經過onRemoveItem函數來移除增組件。
onRemoveItem(i) {
    console.log(this.state.widgets)
    this.setState({
      widgets: this.state.widgets.filter((item,index) => index !=i)
    });

  }
複製代碼

後記

感謝支持。若不足之處,歡迎你們指出,共勉。bash

若是以爲不錯,記得 點贊,謝謝你們 😂前端框架

歡迎關注 個人:【Blog】【Github】【掘金】【簡書】架構

相關文章
相關標籤/搜索