為了實現如圖所示的樹狀結構圖,並使列表項可拖動到盒子里,研究了ztree這個插件的使用,並仔細研究了列表項的拖動事件。完成了預期需求,對jQuery的運用得到了提高。這個插件的功能非常強大,除了基本的簡單樹結構外,還支持自定義圖標、自定義字體、單擊節點控制、異步加載節點數據等多種擴展功能。本文只介紹一下基本樹的實現,需要擴展功能的話,可以參考其API根據項目需求靈活展開工作。官網地址為:http://www.treejs.cn/v3/demo.php#_101
需求圖

實現:首先我們先下載ztree這個插件,解壓后會發現里面文件很多,那是因為這個插件涵蓋了各種需求的實現文件。找到中文(CN)目錄下的文件,根據頁面demo來實現我們的需求,首先引入核心庫jquery-1.9.1.min.js,jquery.ztree.core.js,zTreeStyle.css,別忘了img這個文件夾,如果缺失可能會導致樹顯示的不完整,文件夾也顯示不出來。引入這些后,還需要在需要放置li列表的ul上面添加一個class="ztree"。使用這個的時候踩過兩個坑,一個就是img文件夾未添加,一個就是ztree類名未添加,導致反復調試。下面上代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="zTreeStyle.css" type="text/css"> <script src="jquery-1.9.1.min.js"></script> <script src="jquery.ztree.core.js"></script> <style> .divT li{ list-style: none; } </style> </head> <body style="padding-left: 140px"> <div class="content_wrap"> <div class="zTreeDemoBackground left"> <ul id="ulDiv" class="ztree"></ul> </div> </div> <div class="divT" id="box1" style="width:200px;height:200px;border:1px solid red"> </div> <div class="divT" id="box2" style="width:200px;height:200px;border:1px solid red"> </div> <div class="divT" id="box3" style="width:200px;height:200px;border:1px solid red"> </div> <script> var setting = { }; var zNodes =[ {name:"條目列表", open:true, children: [ { name:"葉子節點1"}, { name:"葉子節點2"}, { name:"葉子節點3"}, { name:"葉子節點4"}, { name:"葉子節點5"}, { name:"葉子節點6"}, { name:"葉子節點7"}, { name:"葉子節點8"}, { name:"葉子節點9"} ]} ]; $(document).ready(function(){ $.fn.zTree.init($("#ulDiv"), setting, zNodes); var liDoms = $('#ulDiv_1_ul li'); //循環設置每個子項的draggable屬性,以及時候拖動標記 liDoms.each(function (index) { this.draggable='true'; this.flag=false; this.ondragstart=(function (k) { return function () { this.flag=true; console.log('第'+(k+1)+'項開始移動') } })(index); this.ondragend=(function (k) { return function () { this.flag=false; } })(index); }); //投放區事件 var acceptDiv=$(".divT"); acceptDiv.each(function (index) { this.ondragenter=(function(k){ return function (e) { e.preventDefault(); } })(index); this.ondragover=(function(k){ return function (e) { e.preventDefault(); } })(index); this.ondragleave=(function(k){ return function (e) { e.preventDefault(); } })(index); this.ondrop = (function(k){ return function (e) { e.preventDefault(); liDoms.each(function () { if(this.flag){ $('.divT:eq('+k+')').append(this); console.log('落地在第'+(k+1)+'個盒子'); } }); } })(index); }); }); </script> </body> </html>
可以看到,ul下面的列表li是由zNodes這個數組渲染出來的,在渲染並填充好列表后我們才能對其進行綁定操作,因此要注意事件添加的先后順序,否則會達不到預期效果。首先循環設置每個子項,下面對子項的拖拽事件做一個介紹。
①draggable屬性:標簽元素要設置draggable=true,否則不會有效果,例如上述代碼中將每個li節點的屬性設置為draggable='true';
②ondragstart事件:當拖拽元素開始被拖拽的時候觸發的,此事件作用在被拖拽元素上。
③ondragover事件:拖拽元素在目標元素上移動的時候觸發的事件,此事件作用在目標元素上。
④ondragend事件:當拖拽完成后觸發的事件,此事件作用在被拖拽元素上。
⑤ondrop事件:被拖拽的元素在目標元素上同時鼠標放開觸發的事件,此事件作用在目標元素上。
⑥ondragenter事件:當拖拽元素進入目標元素的時候觸發的事件,此事件作用在目標元素上。
在上述代碼中,Event.preventDefault()方法用來阻止默認的事件方法等執行。在Ondragover中一定要執行preventDefault(),否則ondrop事件不會被觸發。Event.effectAllowed屬性,就是拖拽的效果。
實現了如下預期功能:

異步加載節點數據
setting設置如下所示,具體API可查看官網,此時url根據單擊節點的不同而動態設置,根據層級的不同需要調整相應設置。
var setting = { data:{ simpleData:{ enable:true } }, view:{ showIcon:false,//設置是否顯示圖標 showLine:true//設置是否顯示線條 }, async: { enable: true, type:"get", url:function (treeId,treeNode) { console.log(treeNode.ID); return '/api/group/'+treeNode.ID+'?param=&proxy=eyJQcm90b2NvbCI6IkNsb3NlbGkiLCJVc2VybmFtZSI6IjE4ODg4ODg4ODg4IiwiUGFzc3dvcmQiOiJBcmNzb2Z0MDEiLCJWZW5kb3IiOiJIZW11U21iIn0%3D'; }, autoParam:["id", "name=n", "level=lv"], otherParam:{"otherParam":"zTreeAsyncTest"}, dataFilter: filter } }; function filter(treeId, parentNode, data) { var childNodes=data.Result.Children; if (!childNodes) return null; console.log(childNodes); console.log(999); childNodes.map(function (x) { x.isParent=true; return x; }); var i,l=childNodes.length; for (i=0; i<l; i++) { childNodes[i].name = childNodes[i].Name.replace(/\.n/g, '.'); } return childNodes; } var zNodes =[ {Name:data.Result.Name, open:true,isParent:true, children: data.Result.Children.map(function (x) { x.isParent=true; return x; }) } ]; $.fn.zTree.init($("#dev-list"), setting, zNodes);
