Element的el-tree控件后臺數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取
最近用到了el-tree控件,主要是數(shù)據(jù)的格式,按照官網(wǎng)的數(shù)據(jù)格式來就可以顯示節(jié)點的樹形結(jié)構(gòu)了。
代碼參考很多
這里給出一個比較好的鏈接:http://www.dbjr.com.cn/article/181990.htm
代碼說明在注釋里寫的很詳細了已經(jīng),這里不再敘述說明。至于為什么抽取成這種格式的數(shù)據(jù),那是因為ElementUI-tree規(guī)定的數(shù)據(jù)格式,你想要用這個控件,就必須按照他們規(guī)定的這個格式 來。
數(shù)據(jù)格式如下:
Controller代碼
@RequestMapping("/cateList") @ResponseBody public List<TbCategory> cateList() { // 整體思路: // 1、取得所有數(shù)據(jù)、放入集合List1 (tbCategories) // 2、將List1所有數(shù)據(jù)都放入到map(treeMap)中:元素id為鍵,元素本身對象為值 // 3、取得頂層節(jié)點放入集合List2中(resultList) // 4、遍歷List1中的所有數(shù)據(jù),通過數(shù)據(jù)的parentId為鍵在map中取值 // 1)如果能取到,則說明該元素有父節(jié)點 // 1、判斷該父節(jié)點下的childList中是否有已經(jīng)子節(jié)點 // 1、若無:則創(chuàng)建一個集合,將子節(jié)點放入 // 2、若有:則直接將子節(jié)點放入即可 // 5、把放好的數(shù)據(jù)放回到map中 // 6、返回List2(resultList) // 注意:整個過程將所有數(shù)據(jù)取出放入list2(resultList),返回的也是 //list2 List<TbCategory> tbCategories = categoryService.cateList(); List<TbCategory> resultList = new ArrayList<TbCategory>(); // 存貯頂層的數(shù)據(jù) Map<Object ,Object> treeMap = new HashMap(); Object itemTree; for(int i = 0;i<tbCategories.size() && !tbCategories.isEmpty();i++){ itemTree = tbCategories.get(i); treeMap.put(tbCategories.get(i).getNodeId(),tbCategories.get(i));// 把所有的數(shù)據(jù)都放到map中 } // 這里也可以用另一種方法,就是拿到集合里的每個元素的父id去數(shù)據(jù)庫中查詢,但是,這樣與數(shù)據(jù)庫的交互次數(shù)就太多了 // 遍歷map得到頂層節(jié)點(游離節(jié)點也算作頂層節(jié)點) for(int i =0;i<tbCategories.size();i++){ // 優(yōu)點1:整個方法,只查詢了一次數(shù)據(jù)庫 // 優(yōu)點2:不用知道頂層節(jié)點的id if(!treeMap.containsKey(tbCategories.get(i).getParentId())){ // 我們在存儲的時候就是將元素的id為鍵,元素本身為值存入的 // 以元素的父id為鍵,在map里取值,若取不到則,對應(yīng)的元素不存在,即沒有父節(jié)點,為頂層節(jié)點或游離節(jié)點 // 將頂層節(jié)點放入list集合 resultList.add(tbCategories.get(i)); } } // 循環(huán)數(shù)據(jù),將數(shù)據(jù)放到該節(jié)點的父節(jié)點的children屬性中 for(int i =0 ;i<tbCategories.size()&& !tbCategories.isEmpty();i++){ // 數(shù)據(jù)庫中,若一個元素有子節(jié)點,那么,該元素的id為子節(jié)點的父id //treeMap.get(tbCategories.get(i).getParentId()); // 從map集合中找到父節(jié)點 TbCategory category = (TbCategory)treeMap.get(tbCategories.get(i).getParentId()); if(category!=null ){ // 不等于null,也就意味著有父節(jié)點 // 有了父節(jié)點,要判斷父節(jié)點下存貯字節(jié)點的集合是否存在,然后將子節(jié)點放入 if(category.getChildList() == null){ // 判斷一個集合是否被創(chuàng)建用null:表示結(jié)合還沒有被分配內(nèi)存空間(即還沒有被創(chuàng)建),內(nèi)存大小自然為null // 用集合的size判斷集合中是否有元素,為0,沒有元素(集合已經(jīng)被創(chuàng)建), category.setChildList(new ArrayList<TbCategory>()); } category.getChildList().add(tbCategories.get(i)); // 添加到父節(jié)點的ChildList集合下 // 這一步其實可以不要,因為我們修改了數(shù)據(jù)(添加了子節(jié)點,然后在將元素放入到map中, // 若鍵相同,map會自動覆蓋掉相同的鍵值對,達到更新map集合中的數(shù)據(jù)的目的),但是我們 // 這里只是從map中取值,而并不關(guān)心值的子節(jié)點(子節(jié)點是對象本身自己封裝的。這里我們知道 // 元素從查詢后放入map,父節(jié)點放入list,然后通過鍵來在map中取得對象,之后再將修改過的對象重新放入map當中 // ,我們并沒有直接操作list,但是在list中對象的值卻是已經(jīng)修改過了,這就是對象的引用傳遞,同一個引用對象是通過 // 地址值來操作對象的,即有不同的引用,但是對象中的屬性是已經(jīng)通過引用的操作而改變的,所以這里一旦修改過后,無論是map中還是list中,再次取值時都已經(jīng)是更改過后的值了) treeMap.put(tbCategories.get(i).getParentId(),category); // 把放好的數(shù)據(jù)放回到map中 } } return resultList; }
實體類:
private Long nodeId; private String categoryName; private Long parentId; private Long childId; private List<T> childList;
以上數(shù)據(jù)都在后臺封裝好了,前臺直接獲取數(shù)據(jù)顯示即可
<el-tree :data="treeList" :props="defaultProps" @node-click="handleNodeClick" node-key="nodeId" show-checkbox=true> </el-tree>
js:
defaultProps:{ children: 'childList', label: 'categoryName' // 這里的名字要和你封裝的數(shù)據(jù)中的節(jié)點的名字一樣 } // 點擊事件 handleNodeClick: function (data) { console.log("沒做處理"); }
方法抽取
上面的方法雖然也能用,但是想把這個方法抽取成一個通用的方法,以后再寫的時候就可以直接調(diào)取該方法了。抽取的過程中還是遇到了很多的問題的。
例如實體類A是對應(yīng)數(shù)據(jù)庫中存儲節(jié)點的表的實體類,但是,實體類中是不存在setChildList、getChildList集合這些方法的。我就把這些存貯信息的字段寫在了一個工具類里面,然后方法也在該工具類里。這樣返回的時候就要返回一個裝有該工具類的一個集合了。還有一個問題就是該工具類中都需要那些字段?因為是一棵樹,所以我們需要節(jié)點id,幾點的父id,節(jié)點的名稱,以及存儲子節(jié)點的集合,如果想要更多的數(shù)據(jù),可以添加一個 T data泛型,該泛型直接將原本存儲節(jié)點的實體類對象存儲進來。這樣所有的數(shù)據(jù)就都整齊了,數(shù)據(jù)結(jié)構(gòu)也就完整了。
contrell代碼:
因為我們想抽取一個公用的方法,那么參數(shù)的類型就是不確定的,即傳入的list中元素的類型是不固定的,所以要用到泛型。上面說過了,我們要拿到節(jié)點id,父id,以及節(jié)點的名稱賦值給工具類中對應(yīng)的字段。但是既然是用泛型,所以就不知道對象類型,所以我們在工具類中是點不出相應(yīng)的方法來取到值的,我們就要用到反射,反射的知道類中具體的字段或者方法的名字來取值,所以我們在controller來調(diào)用工具類的時候就要,將節(jié)點id、父id和節(jié)點名稱傳入。當然了還要傳入從后臺查詢到了裝有數(shù)據(jù)的list集合。
contreller代碼如下所示:
@RequestMapping("/cateList") @ResponseBody public List<TreeUtils> cateList() throws Exception{ List<TbCategory> tbCategories = categoryService.cateList(); List<TreeUtils> treeList = TreeUtils.getTreeList(tbCategories,"nodeId", "parentId", "categoryName"); return treeList; }
工具類:
// 抽取方法的時候要考慮一個問題,即,返回一個集合,集合中有父節(jié)點和字節(jié)點,父節(jié)點和字節(jié)點的類型一定要統(tǒng)一, // 即這里返回的是一個裝有TreeUtils類型的集合,那么集合里的父節(jié)點和子節(jié)點一定都得是TreeUtils類型的 public class TreeUtils<T> { private Integer id; // 節(jié)點id private Integer parentId; // 父節(jié)點 private String name; // 節(jié)點名稱 ,返回給前臺的是一個裝有TreeUtils的集合的數(shù)據(jù),所以在前臺顯示數(shù)據(jù)的時候,el-tree的lable的名字的和這個一樣 private List<TreeUtils> childList; // 父節(jié)點中存放子節(jié)點的集合 private T data; // 節(jié)點數(shù)據(jù)
方法
/** * @param listData // 從數(shù)據(jù)庫中查詢的數(shù)據(jù) * @return */ public static List<TreeUtils> getTreeList(List<?> listData ,String id,String parentId,String categoryName) throws Exception{ List<TreeUtils> resultList = new ArrayList<TreeUtils>(); // 最終返回的結(jié)果 Map<Integer ,Object> map = new HashMap<Integer,Object>(); for(int i =0;i<listData.size() && !listData.isEmpty();i++){ // 寫一個與該方法差不多的方法,將得到TreeUtils的代碼抽取出來 // 也可以將listData集合整個轉(zhuǎn)換成裝有TreeUtils的集合x,然后再循環(huán)x TreeUtils treeUtils = new TreeUtils(); treeUtils.setId(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString())); // id // 返回值為Object無法直接轉(zhuǎn)換成Integer,先toString,再轉(zhuǎn)換成Integer。這里的返回值寫成Object是因為多種類型字段的值都可以用該方法 treeUtils.setParentId(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),parentId).toString())); // 父id treeUtils.setName(TreeUtils.getFileValue(listData.get(i),categoryName).toString()); // 節(jié)點名 //System.out.println("節(jié)點名為+"+TreeUtils.getFileValue(listData.get(i),categoryName).toString()); treeUtils.setData(listData.get(i)); // data:原對象中的所有屬性,無children // 通過反射得到每條數(shù)據(jù)的id將數(shù)據(jù)封裝的map集合中,id為鍵,元素本身為值 map.put(treeUtils.getId(),treeUtils); // 將所有頂層元素添加到resultList集合中 //if( 0 == treeUtils.getParentId()){ // resultList.add(treeUtils); // } } // 得到所有的頂層節(jié)點,游離節(jié)點也算作頂層節(jié)點 // 優(yōu)點一,不用知道等級節(jié)點的id // 優(yōu)點而,只查詢了一次數(shù)據(jù)庫 for(int i =0;i<listData.size();i++){ if(!map.containsKey(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),parentId).toString()))){ resultList.add((TreeUtils) map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString()))); } } for(int i =0;i<listData.size() && !listData.isEmpty();i++){ TreeUtils obj = (TreeUtils)map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i), parentId).toString())); if(obj != null){ if(obj.getChildList() == null){ obj.setChildList(new ArrayList()); } obj.getChildList().add(map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString()))); } } return resultList; }
反射的方法
/** * 通過反射得到的數(shù)據(jù)類型的也是不一定的,所以這里我們返回值為Object * Object是無法直接轉(zhuǎn)為Integer,現(xiàn)將Object轉(zhuǎn)為String,然后再將String轉(zhuǎn)為Integer * @param item * @param fileName * @return */ public static Object getFileValue(Object item,String fileName) throws Exception { Class<?> aClass = item.getClass(); Field file = aClass.getDeclaredField(fileName); // 得到所有字段包括私有字段 file.setAccessible(true); // 取消訪問限制 return file.get(item); // 這里就體現(xiàn)出反射的意思了,我們通常都是通過對象拿到字段,這里是通過字段,將類的字節(jié)碼對象為參數(shù)傳入,來得到值 }
ps:抽取方法遇到了很多的問題,其中的T,?等泛型還只是會簡單的用,并不熟練,以后要多加學習。
到此這篇關(guān)于Element的el-tree控件后臺數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取的文章就介紹到這了,更多相關(guān)Element el-tree生成及方法抽取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+element樹組件 實現(xiàn)樹懶加載的過程詳解
這篇文章主要介紹了vue+element樹組件 實現(xiàn)樹懶加載的過程,本文通過圖文實例代碼相結(jié)合給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10解決vue數(shù)據(jù)不實時更新的問題(數(shù)據(jù)更改了,但數(shù)據(jù)不實時更新)
這篇文章主要介紹了解決vue數(shù)據(jù)不實時更新的問題(數(shù)據(jù)更改了,但數(shù)據(jù)不實時更新),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10antd?Vue實現(xiàn)Login登錄頁面布局案例詳解?附帶驗證碼驗證功能
這篇文章主要介紹了antd?Vue實現(xiàn)Login登錄頁面布局案例詳解附帶驗證碼驗證功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05