1. 程式人生 > >EasyUi TreeGrid封裝

EasyUi TreeGrid封裝

val 表單 text mod 分層 導圖 一次 大量 兩個

http://www.cnblogs.com/Leo_wl/p/4319470.html

禮物一:樹型實體的抽象與封裝

  所謂樹型實體,就是具有樹型結構關系的實體,比如省、市、區。對於初學者,可能會創建三張表進行存儲,有經驗的開發者通過引入ParentId將設計簡化為一張表,但是基於ParentId的設計也不夠完美,主要問題是查找某個節點的所有上級或所有下級時,都需要進行遞歸,這是一個低效而復雜的操作。

  更有經驗的開發者會引入物化路徑Path,物化路徑是對節點關系的記錄,一般格式為:當前節點Path = 父節點Path + 當前節點Id + “,”,註意物化路徑的最後一定是某個符號,一般為逗號。

  一旦物化路徑設置完成,查找所有上級和下級就非常簡單,查找所有上級只需要從當前節點的Path中,用逗號分隔出Id即可,查找所有下級,通過StartsWith查詢Path列,也就是Sql中的Like ‘xxx%’。

  雖然物化路徑在查詢節點關系方面非常高效,但也不是沒有成本的,主要成本在於修改節點關系之後,該節點的所有下級節點的物化路徑都需要更新。比如某個節點修改了父節點,那麽除了當前節點的Path需要更新外,它的所有下級節點也需要更新,這是一個代價高昂的操作。想像一下,當一個節點下面有數千個,甚至數萬個節點,修改一下節點關系將帶來多麽嚴重的後果。不過一般樹型結構的數據量都不會很大,所以這個問題也不用太多考慮,你只需要了解用這種設計方案有什麽弊端即可。

  當使用了EasyUi的TreeGrid這種控件以後,可以在表格上隨意編輯和修改,甚至可以通過拖拽的方式修改父節點,僅在最後一刻進行保存,而保存的時候使用工作單元DbContext進行操作,這時候你會發現物化路徑的更新將是一個非常棘手的問題。

  樹型結構也有規律可循,甚至TreeGrid上的操作都可以進行抽象,我在領域層定義了ITreeEntity、TreeEntityBase、ITreeEntityQuery、TreeEntityQuery等幾個類和接口,應用層定義ITreeBatchService、TreeBatchService,表現層定義基控制器TreeGridControllerBase。通過這幾個類進行抽象,樹型結構的基本操作都內置到框架中,業務類通過繼承基類就完成了大部分工作。

  值得一提的是, TreeGridControllerBase提供了一個加載模式LoadMode,默認為異步加載模式,每次只查詢一級節點。具體控制器通過重寫加載模式,可以切換為同步加載,即一次加載全部節點,另外還提供了一種根節點異步加載模式,即根節點異步加載,下級節點同步加載,通俗的說就是第一次只加載根節點,點擊根節點查詢出全部子節點。當然,這些功能都不需要你手寫代碼,全部內置。

  由於本篇只是簡介,後續文章再詳細介紹。

禮物二:EasyUi TreeGrid抽象與封裝

  對於樹型實體的編輯操作,一般可以使用Tree控件,再配合一個表單或表格進行,但TreeGrid是更好的選擇。

  Easyui treegrid 有很多小bug,比如getChanges方法獲取的結果不正確,分頁總行數錯誤等,這些問題都需要自己解決。

  我對treegrid的封裝,除了修復一些bug外,另外對樹型表格上的操作進行了抽象,將基本操作都內置到框架中。

  大體功能如下:

  1. 表格編輯
  2. 添加根節點
  3. 添加下級節點
  4. 插入同級節點(上方)、
  5. 插入同級節點(下方)
  6. 自動創建連續的排序號(服務端+客戶端配合完成)
  7. 上移
  8. 下移
  9. 拖拽排序
  10. 修正排序號
  11. 拖拽修改父節點
  12. 限制可拖拽的層級
  13. 批量修改,一次保存
  14. 凍結節點
  15. 啟用節點
  16. 支持不同加載模式
  • 同步加載模式
  • 異步加載模式
  • 根節點異步加載模式

  17. 支持對根節點(第一級節點)分頁

  18. 支持查詢時顯示所有上級節點

  19. 支持右鍵菜單

  先來幾個截圖。

技術分享

技術分享

技術分享

技術分享

技術分享

  對於表格上的編輯操作,我是用官方提供的edatagrid擴展,復制了一份來改造的,拖拽使用的是官方提供的treegrid.dnd擴展,也簡單改了下 。

  關於easyui的性能,如果使用datagrid控件很慢,一般是因為沒有設置列寬,這是必須設置的,不然奇慢。Treegrid雖然從datagrid控件派生,但行為上很多不同,datagrid操作行索引index,而treegrid操作的是id。

  我在封裝treegrid的時候發現,40個節點左右,treegrid提供的所有操作id的方法都非常慢,斷點調試能明顯感覺卡一下。由於沒有源碼,無法調優,所以你在使用我提供的拖拽排序和修正排序號這些功能時,發現性能很差不要驚訝,為何純客戶端操作會如此之慢,那是easyui底層的問題,因為需要調用它的相關方法。

  至於你擔心我封裝的服務端控件解析可能存在性能問題,一般不需要太緊張,我目前沒有考慮性能,一旦服務端控件解析成為性能瓶頸,我會優化它。

  另外一點,由於是一次性保存,可能會批量更新很多節點,對此我沒有進行性能優化,使用的是EF的對象一個個的更新,可能會比較慢,不過考慮到這些操作一般是管理員幹的,慢一點就讓他忍忍好了。

  封裝以後,業務代碼就非常簡單了,控制器代碼如下。

技術分享

  視圖還是那麽幹凈,一行js都沒有,代碼如下。

技術分享

  可以看到,雖然treegrid與datagrid顯著不同,但封裝之後,基本沒啥區別,大量降低了學習成本(關於過度封裝的危害,我後續文章再述)。

禮物三:EasyUi ComboTree控件的抽象與封裝

  效果如下圖所示。

技術分享

  調用代碼如下。

技術分享

禮物四: EasyUi ComboBox 控件的抽象與封裝

  支持了N級聯動,這在省市區這類場景非常有用,使用非常簡單,設置父控件的Child方法即可。

  另外支持了值的延遲加載,easyui默認提供的value並不好用,當控件加載完成之前,會在文本框中顯示出來,很難看,我提供了一個LazyValue來設置值,僅當控件加載完畢才開始設置值。

禮物五:通用業務模塊之字典管理

  字典是業務系統中一個重要的模塊,而且也是一個通用模塊,我將這個模塊開放出來供大家參考和使用。

  由於字典是一個樹型結構,所以直接繼承樹型實體相關基類即可,采用treegrid進行編輯,註意字典控制器重寫了加載模式為根節點異步加載,當你點擊根節點時,會展示全部下級節點。

技術分享

  同時,我還提供了一個思維導圖供大家參考,我一般采用思維導圖來整理需求。這個文件在Document項目中。

技術分享

  字典管理采用treegrid,這只是進行編輯,那麽如何使用它呢?

  我們可以采用combotree控件來展示,如下圖所示。

技術分享

  該如何調用方便呢?可以直接調用combotree控件,然後設置服務端url。

技術分享

  但這是最簡單的調用方式嗎?不是,上面的調用需要記住url和其它一些參數,所以還是容易出錯,我們再進行一層封裝。

技術分享

  你只需要傳遞一個code,即字典編碼,這才是最簡單的調用方式。通過本示例,你會發現封裝是分層次的,必須層層封裝才能讓工作更簡單,當你的業務UI組件大量封裝以後,不僅整個系統簡單優雅,開發難度將顯著降低,而且學習成本也大幅下降。

禮物6:通用業務模塊之地區管理

  地區管理也是一個重要的通用模塊,並且也是基於樹型結構,所以這次順便開放出來。

技術分享

  封裝很簡單,主要依賴combox的N級聯動和延遲設置值。

技術分享

  調用代碼如下。

技術分享

  由於EasyUi坑很多,沒有一個照應將會走不少彎路,所以特開一個EasyUi專群(157809322),本群僅限EasyUi開發者,以後碰到問題,大家互相幫助。

  下一篇將繼續介紹表現層和MVC——MVC的封裝和抽象。

  這回下載提供了兩個數據庫,請下載後還原,就可以看到效果了,無法還原的使用PD導出腳本。

  同誌們記得推薦哦,下載地址:

  http://files.cnblogs.com/files/xiadao521/Applications.2015.3.5.1.rar

  http://files.cnblogs.com/files/xiadao521/Framework.2015.3.5.1.rar

  http://files.cnblogs.com/files/xiadao521/Data.2015.3.5.1.rar

  最後,祝各位新年快樂,元宵快樂,吉祥如意。

  .Net應用程序框架交流QQ群: 386092459,歡迎有興趣的朋友加入討論。

  .Net Easyui開發交流QQ群(本群僅限Easyui開發者,非Easyui開發者勿進):157809322

  謝謝大家的持續關註,我的博客地址:http://www.cnblogs.com/xiadao521/

EasyUi TreeGrid封裝