前言
做前端的小伙伴们可能会经常遇到做一个自定义dashboard这样的需求。 那么什么是自定义dashboard呢?自定义dashboard其实就是一个自定义面板,用户能够在面板上自由的拖拽,新增,删除组件。组件可以是各种echarts图形,也可是各种数据表格。通过各个组件的拖拽组合,从而让用户自定义想要看到的面板。
项目预览
源码地址 组件可以动态添加,删除,可以自由拖拽,缩放。并且缩放后组件内部的echarts图表也会跟着缩放。
技术架构
- 前端框架:React
- UI库:Ant Design
- 脚手架:create-react-app
- 拖拽插件:react-grid-layout
技术实现
1. 使用npm安装react-grid-layout包
1
npm install react-grid-layout
2. 插件声明及样式引入
首先,在js文件中引入WidthProvider和Responsive组件,并且实例化响应式拖拽组件。 其次,在css文件中引入插件的样式。
1
2
import { WidthProvider, Responsive } from "react-grid-layout";
const ResponsiveReactGridLayout = WidthProvider(Responsive);
1
2
@import '~react-grid-layout/css/styles.css';
@import '~react-resizable/css/styles.css';
3. Render渲染
在React的render方法中渲染可拖拽布局。ResponsiveReactGridLayout组件有多个属性,这里举几个比较重要的说明一下:
- cols:定义了响应式布局划分成几列。
- rowHeight:响应式布局中组件的行高。
- onLayoutChange:当响应式布局中的组件发生拖拽或者放大缩小时触发该函数。
1
2
3
4
5
6
7
8
9
10
<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属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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=
/>
)
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值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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函数来移除增组件。
1
2
3
4
5
6
7
onRemoveItem(i) {
console.log(this.state.widgets)
this.setState({
widgets: this.state.widgets.filter((item,index) => index !=i)
});
}
后记
感谢支持。若不足之处,欢迎大家指出,共勉。
如果觉得不错,记得 点赞,谢谢大家 😂