根據公司的業務需求我是這樣封裝組件

前言

一個項目下來發現有不少看似類似但又有區別的功能,想一想若是一個一個的去寫這種類似又有區別的功能,就會顯的乏味枯燥,並且更關鍵的是這樣的代碼使得項目更難的去維護。如何讓項目面目一新,而且方便之後需求迭代的時候更好的維護呢?vue

那就動手封裝組件吧,讓那些類似的功能需求都統一管理統一配置。git

需求

當我拿到需求的時候,我先看了element-ui的組件是否知足我業務上的需求(ps:若是在elemnt-ui組件的基礎上去作改造也是ok的),但後來我發現element-ui的表格組件沒法知足我此次的業務需求,經過改造element-ui當中的組件也超級麻煩。最後,我仍是決定本身封裝一個多功能的table組件吧.......github

功能需求以下:web

1.表格數據的樹形渲染而且同個父級下的同層級可拖拽,不一樣層級沒法完成拖拽。npm

2.表格行可操做(ps:好比編輯,刪除,查看詳情)element-ui

3.表格的頂部可操做(ps:展開,排序)api

4.表格尾部可分頁markdown

5.表格可多選(ps:表格帶複選框)函數

多功能的表格組件

安裝插件

npm install element-ui sortablejs -S
複製代碼

在項目中我是使用sortablejs實現拖拽的,以及使用elemnt-ui的分頁組件實現分頁的功能。oop

樹形結構數據如何渲染

由於是樹形結構的數據,因此我想到了遞歸組件。在設計遞歸組件以前先了解樹形結構的數據是長什麼樣的。

以下圖經過給組件命名recursiveRow,而且在該組件的模板裏使用該組件。好吧,到這裏即完成了遞歸組件的第一步...

我將每一行設計成一個組件,若是該行數據有children那麼就在渲染一次recursiveRow組件。好吧,到這裏實現了遞歸的條件了。 接下來就是完成每一行數據的代碼編寫了。具體如何完成每一行數據的代碼編寫我等後續再補充,接下來咱們先來了接這個組件的配置表。

表頭的配置項設計

這個組件經過表頭的配置實現了組件的統一管理,表頭配置項的設計主要是經過一個JSON來實現的。

JSON是經過字段namepropsbeforeimagesactionsattrselecttreenameprops

基礎配置

表格的基礎配置是經過字段nameprops來設計的。

這樣的基礎配置渲染出來頁面以下:

其餘配置

通常一個表格組件不只僅只有渲染的功能就完事了,還會有其餘的操做,好比刪除,編輯,好比複選框,以及屬性數據的樣式配置等等...

行操做的表頭配置我是經過actions配置進行的,能夠傳遞點擊的事件,而且執行該事件能夠獲取每行的數據,以及改行的索引,還有事件對象。其屬性是經過attr來配置的。

若是須要複選框可經過配置select,將改字段設置爲true。經過配置attr來配置屬性,固然若是不傳也能夠,有默認值。那如何獲取到每行勾選所對應的值呢?留個疑問,後續咱們再講述。

若是肯定了哪一個字段是須要渲染成樹形的圖案,能夠經過配置tree,將改字段設置爲true就能夠,能夠經過配置before能夠特殊渲染每個格子的數據。

當完成表頭配置項的設計以後,如何傳遞屬性,如何設計上面講到的每行編碼就是接下來要考慮的。

這裏的核心是經過 v-bind,當v-bind不帶參數的是將會把整個對象的全部屬性都綁定到當前元素上。以及v-on將事件一一綁定到元素上。 組件中使用了 $attrs對象屬性的集合和

$listeners對象事件的集合來實現屬性的跨階級傳遞,監聽事件的傳遞。將綁定在table組件的屬性和事件經過跨階級傳遞給遞歸組件,使得遞歸組件接收屬性和事件。

自定義遞歸組件:

有了表頭和表格數據就能夠實現每行的編碼了,就是遍歷table數據和表頭數據.,來完成每行的編碼,並將其屬性進行綁定。在實現每行的過程當中,使用了vue提供的一個動態組件component來實現動態的標籤渲染。

功能集合

功能解析說明

  • 在實現業務需求功能的過程中,由於我設計的是遞歸組件,因此每個遞歸組件都是一個做用域。大部分人都會在遞歸當中混淆,它們只不過是層層嵌套的做用域,但它們又是獨立的個體。(ps:在這裏我也踩過坑)

  • 剛剛上面提到的如何獲取每次勾選的值。是經過給table綁定select-change事件,該事件會返回每次所勾選的值。其實現的思想就是保存每次勾選的值,過濾每次反選的值,具體的想了解實現過程可查看源碼。

  • 講到表格的頂部,那我就把尾部一塊兒講了吧。在佈局上頂部和尾部是經過具名插槽slot來實現的。因此可自定義頂部的操做以及尾部的分頁。

  • 表格可展開是經過表格內部暴露出來一個函數openAllTree來實現的,能夠經過綁定ref再外部獲取這個函數。openAllTree其實現的思想是經過改變數據,讓數據去驅動視圖;在遞歸組件中封裝一個函數用來將當前做用域的內部屬性更新,在 table 組件中循環執行每個遞歸組件的函數。具體的想了解實現過程可查看源碼。

  • 表格可排序是經過綁定屬性isSort來開啓和關閉排序功能。給每個遞歸組件綁定一個ref屬性,那麼經過new Sortable實例實現同層級的拖拽(這裏的同層級就是相同層級節點而且同個父節點的可互拖)。其實現的思想是經過綁定ref屬性可獲取當前組件的數據流(ps:由於每個組件都有本身的做用域,因此是獨立的),那麼經過數據再去驅動視圖。在這裏還要注意isSort的數據更改以及拖拽完成以後的表格數據更新,因此在經過接收屬性callback來實現表格數據的更新(ps:回調函數的思想)。內部是經過函數handlerSort實現的,具體的想了解可查看源碼。

  • 表格當前行刪除操做是經過table組件內部暴露的函數handlerDepDel實現的。這裏我考慮到數據是單向流動因此我經過傳參的方式實現樹形結構的數據刪除。(ps:參數是最原始的數據列表和當前行的id)我我的以爲在當前行數據刪除以後,只需調用刪除的接口也就不必再去調用獲取總的數據列表的接口。等下次再進入頁面,從新調用總列表的數據接口便可。

  • 新增了一個open屬性,該屬性表明是否一進入改頁面就打開樹形數據,該屬性默認是false即不打開。

  • 最後在完成公司的業務需求以後,我又本身寫了一個當點擊編輯以後可直接在表格上修改數據的功能。主要是table組件暴露出的一個內部函數handlerEdit。其思路是經過增長改行的字段component來配置修改HTML標籤,以及修改行的該字段的數據。具體的實現可查看源碼。

  • 優化了表格的loading

使用table

自定義組件table

以下圖:

樣式可自行修改哈~~

源代碼

組件源碼地址可查看:源碼地址

後記

爲了知足掘有的需求,我又補充了一個選擇父級以後全部的孩子都會被選中的需求。這裏主要用到的思想就是數據更新視圖以及事件流機制實現數據的獲取。

  • 經過給table組件綁定tree-change事件用來獲取當前父選中以後的數據。

說明

以前的編輯有點小問題此次也一併修復了。

總結

不少人可能會以爲那麼多組件庫爲何要本身封裝組件呢,有這個必要嗎?其實在分析這個需求的時候,我也曾嘗試去找資源,但發現基本上都是文件夾同樣的拖拽功能...因此,我後來就決定自行封裝。

固然在開發的過程中,我以爲封裝組件是有必要的,既不會代碼冗餘顯得臃腫並且還實現統一配置管理可讓項目更穩步的實現迭代。

最後,對各大掘友有幫助的話但願賞個 star ~(ps:不要吝嗇哦)

相關文章
相關標籤/搜索