今天开始实现基于Flutter,仿写Element Table,flutter web 正式版已经很久很久,一直也没有像element,ant 这种组件库。 闲的无聊,仿写试一试!
基于 column row如果去写的话,感觉会陷入嵌套之地狱。我可不想为出师,而放弃!
就在Flutter Table 这个widget 上面二次开发,写了一个简单列子,之后在探究根本!
// 自行看看其效果,感觉就是平平无奇
Table(
children: [
TableRow(
children: [
Text('张三'),
Text('男'),
Text('20'),
]
),
],
)
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
接下来开始我们的二次封装之路,首先看看Element UI语法
对比两个语法,既然仿写就叫,Flutter端就叫 ElTable ElTableColumu
首先写出来需要的Model ElTableColumu 前两个参数就设置必填了
class ElTableColumn {
final String prop;
final String label;
final int? width;
ElTableColumn({required this.prop, required this.label, this.width});
}
ElTable 增加两个属性 children 就是表头,data 就是表数据呗!
class ElTable extends StatefulWidget {
final List<ElTableColumn> children;
final List<Map> data;
ElTable({Key? key, required this.children, required this.data})
: super(key: key);
@override
_ElTableState createState() => _ElTableState();
}
class _ElTableState extends State<ElTable> {
@override
Widget build(BuildContext context) {
return Table(
children: [],
);
}
}
自定义Table 简单实现,实现了简单效果
Table(
children: [
TableRow(
//第一行样式 添加背景色
children: widget.children.map((e) => Text(e.label)).toList()),
for (int i = 0; i < widget.data.length; i++)
TableRow(children: [
for (int j = 0; j < widget.data[i].keys.length; j++)
Text(widget.data[i][widget.data[i].keys.toList()[j]])
]),
],
)
ElTable(
data: [
{
"date": '2016-05-02',
"name": '王小虎',
"address": '上海市普陀区金沙江路 1518 弄'
},
.... 此处省略
],
children: [
ElTableColumn(prop: "date", label: '出生日期'),
ElTableColumn(prop: "name", label: '姓名'),
ElTableColumn(prop: "address", label: '地址'),
],
)
实现简单效果,样式问题后续加入, 但是发现属性 data 里面 key 不对应的prop 会有问题!
解决data 里面key和prop 对应不上问题,思路就是重组 Map
List<Map> newData = [];
@override
void initState() {
super.initState();
for (Map item in widget.data) {
Map newMap = {};
List<String> keys = widget.children.map((e) => e.prop).toList();
for (String key in keys) {
newMap.putIfAbsent(key, () => item[key] ?? "");
}
print(newMap);
newData.add(newMap);
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Table(
children: [
TableRow(
//第一行样式 添加背景色
children: widget.children.map((e) => Text(e.label)).toList()),
for (int i = 0; i < newData.length; i++)
TableRow(children: [
for (int j = 0; j < newData[i].keys.length; j++)
Text(newData[i][newData[i].keys.toList()[j]])
]),
],
);
}
完美
完了,又卡着**el-table-column** 宽度属性,等我细细研究起来
开启谷歌大法!
完美融合,接下来就是怎么根据 ElTableColumn,宽度传入的宽度,动态设置相应的的东西
columnWidths: {
0: FixedColumnWidth(200),
1: FlexColumnWidth(4),
2: FlexColumnWidth(4),
},
完美实现代码,具体效果
Map<int, TableColumnWidth> getColumnWidths() {
Map<int, TableColumnWidth> columnWidth = {};
for (int i = 0; i < widget.children.length; i++) {
if (widget.children[i].width != null) {
if (widget.children[i].width! > 0) {
columnWidth.putIfAbsent(
i, () => FixedColumnWidth(widget.children[i].width!.toDouble()));
}
}
}
return columnWidth;
}
// Table 下面属性
columnWidths: getColumnWidths()
ElTableColumn(prop: "date", label: '出生日期', width: 100),
ElTableColumn(prop: "name", label: '姓名', width: 200),
ElTableColumn(prop: "address", label: '地址'),
简单的列子,感觉也是那么回事了~
😯 鼠标悬浮上,背景颜色发生变化。 开始研究研究......
TableRow 这个widget 上面有 decoration 属性, 可以直接设置color,也就是背景颜色
但是怎么设置鼠标选中事件那,下面精简了代码!
// 鼠标当前状态
int? MouseIndex;
// 背景眼
decoration: BoxDecoration(
color: MouseIndex == i ? Color(0xFFf5f7fa) : null,
border: Border(bottom: BorderSide(color: Color(0xFFdcdfe6)))),
// 事件处理
MouseRegion(
onExit: (e) {
setState(() {
MouseIndex = null;
});
},
onHover: (e) {
if (MouseIndex != i) {
setState(() {
MouseIndex = i;
});
}
},
)
具体用法就这样
ElTable(
data: [
{
"name": '王小虎',
"date": '2016-05-02',
"address": '上海市普陀区金沙江路 1518 弄',
},
{
"date": '2016-05-04',
"name": '王二虎',
"address": '上海市普陀区金沙江路 1517 弄'
},
{
"date": '2016-05-01',
"name": '王三虎',
"address": '上海市普陀区金沙江路 1519 弄'
},
{
"date": '2016-05-03',
"name": '王四虎',
"address": '上海市普陀区金沙江路 1516 弄'
}
],
children: [
ElTableColumn(prop: "date", label: '出生日期', width: 100),
ElTableColumn(prop: "name", label: '姓名', width: 200),
ElTableColumn(prop: "address", label: '地址'),
],
)