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