2020年下半年,有几张图片刷屏:有人骑在自行车上看书,有人边骑车边用电脑,有人床上铺满了一摞摞书……“边骑车边用电脑”的同学被称为“卷王”登上热搜。 慢慢的这些同学毕业了,卷王带着卷走上了社会,带动了其他人一起卷,卷的人越来越多了,苦不堪言,就导致了一些重复造轮子和造一些毫无意义的轮子的现象出现。
造轮子,本来是件好事,但是随着内卷的出现,造轮子就慢慢演变成了一个极端,出现了凭空造轮子和重复造轮子的事情,既不能服务于业务,还使得内卷现象越来越严重,真正的苦不堪言。
分析当前业务遇到的问题,进而产生新的思路和总结,利用技术的手段提升工作效率,提高开发速度,才是真正的有意义的轮子,也不枉卷一场。
场景
CMS(content management system)一词出现已久,通常指的是内容管理系统,是一种位于WEB前端和后端办公系统或流程之间的软件系统。在开发cms后台的过程中,最最常用的应该就是Table了,例如 antd的table:
这应该是最最常用的开发后台管理系统中使用到的组件了,没有个Table,都不好意思说是个cms系统。不过在稍微庞大的业务中会存在一个非常常见的问题,就是一个数据源会有很多很多字段需要进行展示,如果都展示出来呢,就会存在一个非常不美观且乱糟糟的感觉,眼花缭乱。同时不同的人,希望看到的字段也是不一样的,比如A同学希望看到标题0、1、2、3,B同学希望看到标题1、2、3、4,C同学希望看到标题7、8、9、10等。
这样就是一个非常个性化的需求了,如果希望后端同学来参与的话,就会增加后端同学的工作量,同时前端工作也不会相应的减少。得益于浏览器的localstorage存储能力,前端就可以实现,根本不需要后端同学的参与。
实现
首先,既然是antd的Table组件,我们肯定是要基于现有的功能去实现这个需求,所以我们需要在Table组件的基础上套一层,既不能影响Table的展示,同时还能够定制展示列。那我们就可以列一下需求了:
- 不影响Table的展示
- 可以选择自定义展示列
- 可以对展示列进行排序
- 不会对业务产生其他影响(这是最主要的)
需求既然已经明确,我们就可以开整了,具体的实现,就不多说了,我们可以看下实现后的效果:
打磨
既然已经实现了最初的需求,就可以高枕无忧了。怎么可能呢?想太多了吧!!!
是的,后来产品说,现在数据展示列太多了,比之前多了三倍,想在对展示列进行选择的时候进行一下分组,不然都挤在一块密密麻麻的不好找,严重影响工作效率了!
WTF!最见不得别人说影响工作效率了,这么严重的问题怎么现在才说,怎么不早点提需求过来呢?早点提过来肯定早就实现了啊,不会存在影响工作效率的问题啊.
啊!!!我可真是个口是心非的渣男,可是我知道,小蝌蚪才是渣男,我不配啊!!说多了都是泪啊,还是抓紧做需求吧。看下实现效果:
嗯,完美,就是这么个效果。对Table的封装进行了二次修改,在不影响之前的使用方式的基础上,增加了对分组的能力支持,我可真TM棒!
> 然而,快乐的时光总是那么短暂啊~~
有一天,我们的另外一个平台发现,咦,你这个功能还怪好用嘞,能不能给我们也用用,好吧,最简单直接的方式是复制粘贴呀。复制粘贴到一半的时候,突然又来了一个人也想用用这个功能,WTMD就很头大。
这么说来,还是封装成一个npm包吧,等我会,我给你们发布成一个组件包,你们直接安装使用即可。
npm i manage-table
复制代码
尽管拿去用吧。
使用
安装
npm i manage-table
or
yarn add manage-table
复制代码
manage-table组件有对应的peerDependencies
,如果没有安装的话,需要手动安装一下对应的依赖:
"peerDependencies": {
"@ant-design/icons": "^4.6.4",
"antd": "^4.12.0",
"react": "^17.0.0",
"react-beautiful-dnd": "^13.1.0"
}
复制代码
使用方式-: 直接引用,使用内置设置
代码如下:
import ManageTable from "manage-table";
import './App.css';
import React from "react";
function App() {
const mockColumns = new Array(50).fill('').map((_item: string, index) => {
return {
dataIndex: 'title' + index,
key: 'title' + index,
title: '标题' + index,
show: index % 3 === 0,
};
});
mockColumns.push({
dataIndex: 'action',
key: 'action',
title: '操作',
show: true,
});
return (
<div className="App">
<ManageTable name="testTable" columns={mockColumns}/>
</div>
);
}
export default App;
复制代码
效果如下:
使用方式二:自定义header部分
代码如下:
import React from "react";
import { Button } from "antd";
import ManageTable from "manage-table";
export default function App2() {
const mockColumns = new Array(50).fill("").map((_item, index) => {
return {
dataIndex: "title" + index,
key: "title" + index,
title: "标题" + index,
show: index % 3 === 0
};
});
mockColumns.push({
dataIndex: "action",
key: "action",
title: "操作",
show: true
});
const ref = React.createRef();
const handleShowModal = () => {
ref.current.showModal();
};
const SettingHeader = (
<div style={{ textAlign: "left" }}>
<Button onClick={handleShowModal}>自定义设置</Button>
</div>
);
return (
<div className="App">
<ManageTable
ref={ref}
SettingComp={SettingHeader}
name="testTable2"
columns={mockColumns}
/>
</div>
);
}
复制代码
效果如下:
使用方式三:分组展示
代码如下:
import React from "react";
import { Button } from "antd";
import ManageTable from "manage-table";
const mockGroup = () => {
const data = new Array(4).fill('').map((_item:string, index: number) => {
return {
title: '分组' + index,
records: new Array(10).fill('').map((_item: string, indx) => {
return {
dataIndex: 'title' + index + '_' + indx,
key: 'title' + index + '_' + indx,
title: '标题' + index + '_' + indx,
show: indx % 5 === 0,
};
}),
};
});
// 任何一个索引都可以,不必须是0
data[0].records.push({
dataIndex: 'action',
key: 'action',
title: '操作列',
show: true,
})
return data;
}
export default function AppGroupRef() {
const ref: any = React.createRef();
const handleSet = () => {
ref.current.showModal();
}
const SettingHeader = (
<div style={{textAlign: 'left'}}>
<Button type="primary" onClick={handleSet}>自定义设置</Button>
</div>
);
return (
<div className="App">
<ManageTable ref={ref} SettingComp={SettingHeader} name="testTableGroup" columns={mockGroup()}/>
</div>
);
}
复制代码
效果如下:
其他方式
除了可以上面三种方式使用之外,还支持固定展示的配置,即部分字段默认展示且不允许进行排序和删除。manage-table默认是存储在浏览器的缓存里面的,是跟随浏览器走的,如果不想走浏览器缓存,而是自定义存储的话,也是支持的。
具体如下:
ManageTable, 继承自antd的Table
参数名 | 类型 | 说明 |
---|---|---|
name | string | 存储所使用的唯一的key,必传 |
columns | ManageColumnType[] | GroupManageColumn[] |
ref | React.createRef()的返回对象 | 增加面板, 非必传 |
SettingComp | React.ReactNode | 自定义设置头部, 非必传 |
setTitle | React.ReactNode、string | 自定义弹窗的标题,默认'设置显示字段', 非必传 |
defaultShowKeys | string[] | 默认显示的字段,不需要进行选择or 排序 |
initialShowKeys | string[] | 初始显示的字段,自定义存储 |
onKeysSelected | (keys: string[]) => void | 存储钩子函数,搭配自定义存储使用 |
ManageColumnType, 继承自antd的Table的ColumnType
参数名 | 类型 | 说明 |
---|---|---|
show | boolean | 是否默认显示 |
GroupManageColumn, 继承自antd的Table的ColumnType
参数名 | 类型 | 说明 |
---|---|---|
title | string | 组名,必传 |
records | ManageColumnType[] | 列数据, 必传 |
写在最后
欢迎使用和提交反馈。
- 开源代码仓库:manage-table
- npm 地址: manage-table
团队
TNTWeb - 腾讯新闻前端团队,TNTWeb 致力于行业前沿技术探索和团队成员个人能力提升。为前端开发人员整理出了小程序以及 web 前端技术领域的最新优质内容,每周更新 ✨,欢迎 star,github 地址:https://github.com/tnfe/TNT-Weekly
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。