這幾天做動態菜單用到了這個插件,目前用的很廣泛的一個開源框架,最新發布的QUI框架就是用這個插件開發的菜單部分,因此還是很值得深入研究和學習,通過使用感覺功能很豐富,好多函數不用自己開發和編寫,官網上有很詳盡的API可以參考,用着算順手但學習使用的過程中也遇到了一些困難,聽過反復測試和查資料都理解了,但也在思考一個問題,怎么樣才能使得最快的時間從接觸一個新東西到靈活掌握的程度?
這個不僅僅是一個樹形結構的菜單,每個節點左邊可以有一個復選框,看了看也挺簡單的,只需要在setting里面配置一個checked屬性即可。
目前經驗覺得這個用在組織結構、分類、尤其是權限,如果用這個插件完成會很完美和自己的業務邏輯相結合。
原理是很容易理解就不過多說它的原理了,大致同ajax異步請求原理相同,看一遍介紹你也就明白了,這個框架全部是異步請求數據,提高了用戶體驗度。
在學這個過程中,本人有如下幾點浪費了點時間拿出來和大家分享一下,以便大家下次項目中使用更容易上手。
靜態數據與動態數據
這個框架支持XM、json等多種數據格式,建議大家使用json格式數據覺得效果好一些、加載的時候快一些,關於數據格式可以參考官網給的一些數據,官網上面給的都是一些假數據,如果動態生成菜單淡然需要從數據庫里面查詢出來,然后轉換成json字符串了,需要自己解析json字符串。
在之前做項目中還真沒有自己好好研究一下解析字符串,現在用到了只能現學現弄這樣減慢了開發效率,這應該屬於開發基礎。
我自己試着寫幾種方法解析、試着引用網上的方法、幾種迭代都不能生成正確的字符串,最后一種還是解析出來了,從數據庫查詢出來的是list列表,然后把他解析成了一個json串,所有數據都顯示在頂層菜單,檢查json串和給的例子是一樣的但是還是出不來折疊效果。
原來並不是解析json串不對,而是它打印到界面上是一級一級打印,並不是一下全部查出來都打印出去,這樣當然就在一個級別上了,這也是所說的靜態加載全部節點,很讓人惡心的json串,強烈建議大家數量掌握幾種解析json、array等以及相互轉換的方法,這些是很基本的能力,平時會經常用的。
isParent節點
我們一看都知道這個節點表示是不是父節點,它有什么含義呢,在使用中我發isParent為true時,表示的是該節點左邊接受單機事件,也就是會有一個展開符號,每次點擊會觸發一次異步提交數據,請求子節點數據加載到頁面上。正常情況下如果你不點擊父節點所有子節點是不加載到頁面的。
后台生成樹json串代碼
treeList=resourceService.list(childMap); JSONArray jsonArray=new JSONArray(); for(Organization organization:treeList) { JSONObject jsonObject=new JSONObject(); jsonObject.put("id",organization.getId()); jsonObject.put("pid",organization.getPid()); jsonObject.put("name",organization.getName()); //判斷所選擇節點是否是父節點,如果是設置isParent屬性為true,不是設置為false Map subchildMap=new LinkedHashMap(); subchildMap.put("sqlid","SubChildLst"); subchildMap.put("id",organization.getId()); List<Organization> subtreeList=new ArrayList<Organization>(); subtreeList=resourceService.list(subchildMap); if(subtreeList.size() > 0 ) { jsonObject.put("isParent","true"); }else { jsonObject.put("isParent","false"); } boolean isChecked=resourceService.IsChecked(contactid,organization.getId()); if (null==contactid || "".equals(contactid) || "null".equals(contactid)) { jsonObject.put("checked","false"); }else { if (isChecked) { jsonObject.put("checked","true"); }else { jsonObject.put("checked","false"); } } jsonObject.put("open","false"); jsonArray.put(jsonObject); } String json=JsonUtil.toJson(jsonArray);
checked節點
該樹形是選中的節點,這個節點也很有用,比如加載一個商品它是屬於哪些分類的,在加載樹的過程中,要把默認選中的項目加載上來,這個你想怎么實現呢。
動態加載默認選中的節點,用了半天的時間才想出怎么弄,有時候並不是我們不會寫代碼而是沒有思路,有時有思路但是行不通這時就需要我們轉換思考角度,在編程中也要注意從多角度思考,不要鑽到一個點上去。
解決動態加載默認選中項我用的是傳遞參數,在一般的頁面上面傳遞參數覺得很容易,我要用的這個頁面是一個彈出頁面,使用的是window.open屬性,在彈出框上動態加載菜單並把選中的選中,ztree從官網上看API說是不能夠傳遞參數,有一個otherparm屬性可說是只接受靜態參數,是一個一個的鍵值對,我在value處又加了一個js函數,通過這個函數調用父窗體上的一個變量的值,代碼如下;
<SCRIPT type="text/javascript"> var setting = { check: { enable: true, chkStyle: "checkbox", chkboxType : { "Y" : "", "N" : "" } }, //獲取json數據 async : { enable : true, url : "http://127.0.0.1:8080/contact/resource.do?method=getzTreeNodes", // Ajax 獲取數據的 URL 地址 autoParam : [ "id", "name" ], //ajax提交的時候,傳的是id值 otherParam: ["contactid",function(){ return window.opener.document.getElementById("contactid").value; }] }, data:{ // 必須使用data simpleData : { enable : true, idKey : "id", // id編號命名 pIdKey : "pId", // 父id編號命名 rootId : 0 } }, // 回調函數 callback : { onClick : function(event, treeId, treeNode, clickFlag) { if(true) { alert(" 節點id是:" + treeNode.id + ", 節點文本是:" + treeNode.name); } }, //捕獲異步加載出現異常錯誤的事件回調函數 和 成功的回調函數 onAsyncSuccess : function(event, treeId, treeNode, msg){ // alert("調用成功!"); //var nodes=getCheckedNodes(true)); //alert(nodes); }, beforeClick: beforeClick, onCheck: onCheck } }; function beforeClick(treeId, treeNode) { var zTree = $.fn.zTree.getZTreeObj("treeDemo"); zTree.checkNode(treeNode, !treeNode.checked, null, true); return false; } var code; function showCode(str) { if (!code) code = $("#code"); code.empty(); code.append("<li>"+str+"</li>"); } $(document).ready(function(){ $.fn.zTree.init($("#treeDemo"), setting); //setCheck(); }); function onCheck(e,treeId,treeNode) { var zTree = $.fn.zTree.getZTreeObj("treeDemo"), nodes = zTree.getCheckedNodes(true), v = ""; var ids=""; for (var i=0, l=nodes.length; i<l; i++) { v += nodes[i].name + ","; ids+=nodes[i].id+","; } if (ids.length > 0 ) ids = ids.substring(0, ids.length-1); alert(ids); if (v.length > 0 ) v = v.substring(0, v.length-1); cityObjIds=window.opener.document.getElementById("cateSelIds").value=ids; cityObjName=window.opener.document.getElementById("cateSelName").value=v; } function getSelectedNodes() { var zTree = $.fn.zTree.getZTreeObj("treeDemo"), nodes = zTree.getCheckedNodes(true), v = ""; var ids=""; for (var i=0, l=nodes.length; i<l; i++) { v += nodes[i].name + ","; ids+=nodes[i].id+","; } if (ids.length > 0 ) ids = ids.substring(0, ids.length-1); alert(ids); if (v.length > 0 ) v = v.substring(0, v.length-1); //var cityObj = $("#citySel"); //var cityObjIds = $("#citySelIds"); //給父窗體updateContact.jsp中所屬分類賦值 window.opener.document.getElementById("cateSelIds").value=ids; window.opener.document.getElementById("cateSelName").value=v; } function winClose() { window.close(); } </SCRIPT>運行效果,動態下拉列表樹
在工作中別人給你講解代碼或者一點點詳細的講解幾乎是沒有的,我們那個經理只說你用那個ztree做一下那個動態菜單。
作為一個程序員要能讀懂別人代碼
讓我看別人的代碼,我說看着看着就不想看了,還不如我自己動手寫呢,其實,看別人代碼一直覺得挺沒意思的,現在想法改變了些,別人寫的代碼不管是好是壞,我們都值得看一看借鑒借鑒,一直在提高班學習沒有怎么看別人寫的代碼到底是怎么樣的,覺得提高班人寫代碼無論質量如何,風格都是一樣的
注釋多、空行多、格式規范,易讀性很強,這就和學英語一樣,只聽標准音是不行的,需要挺標准音的同時也要聽聽方言,這樣才能讓我們的閱讀代碼的能力真正的提高。
作為一個程序員或者開發人員有不合適的地方要主動解決,並去優化。
前幾天遇到了一個問題,需要通過一個父節點ID,拿到他下面的所有子節點列表或ID,在給我的代碼中用存儲過程實現的但用起來運行效率較慢,項目經理讓我優化優化存儲過程可以看懂但不知道該優化哪里,從網上找了找找到一個算法替換后果然查詢變快了。
說一下學習一個新東西的過程
有時讓你做一個東西往往會用到新東西,一個你沒有接觸過的東西,在這個時候我們怎么樣才能最快的學會了並且把任務做出來。
覺得在項目中該多思考、有時甚至可以不動手但是一定要多去思考,而不是別人告訴你怎么做怎么做,舉一個最簡單的例子post提交和get提交有什么區別?一個不起眼的問題如果你沒有認真思考過,有時在某個時刻你會因此遇到一個小障礙,覺得這個跟解一道數學題一樣,只有把每個知識點理解了、相互之間能聯想到一起,達到各種知識綜合靈活運用,做項目的過程中才誰能得心應手,也容易達到米老師所講的最高境界。