前端框架 (一)zTree 從數據庫中動態加載樹形菜單


        這幾天做動態菜單用到了這個插件,目前用的很廣泛的一個開源框架,最新發布的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提交有什么區別?一個不起眼的問題如果你沒有認真思考過,有時在某個時刻你會因此遇到一個小障礙,覺得這個跟解一道數學題一樣,只有把每個知識點理解了、相互之間能聯想到一起,達到各種知識綜合靈活運用,做項目的過程中才誰能得心應手,也容易達到米老師所講的最高境界。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM