最近公司要求作一個關於後臺的管理系統。在這個mvvm模式橫行的年代,雖然這裏用jquery作項目可能有點不符合時代的潮流,可是管他呢,能作出來先在說唄(公司之後要改用angular或者vue來統一前端的製做方式),我的以爲jquery還挺好用的。廢話這裏就很少敘述了。下面就先來一張完成後的圖片展現一下ztree能夠完成的功能。php
額····這邊彈出層的陰影是錄製軟件的問題(這邊的前端插件用的是layui,想用的小夥伴能夠自行百度layui,順便一提,我這裏用的版本是layui 1.0的,如今layui已經更新到2.0版本了,已經有自適應功能了,挺好用的。你問我爲何不用bootstrap?其實這個項目中UI小夥伴給個人時候插件用的是bootstrap,可是本人就先入爲主了,仍是以爲layui輕便好用,看我的喜愛吧)。css
忘記了初衷這裏是來介紹ztree的,好了,下面先來介紹下ztree的基本信息。html
使用ztree的時候能夠參考官網的教程來一步步跟着作。zTree官網。詳細的api能夠參照着官網來看。前端
先看ztree的初始化過程:vue
1 zTreeObj = $.fn.zTree.init($obj, setting, nodes);
這是就是初始加載ztree樹。第一個參數$obj表明的是你須要加載ztree的容器。通常默認是一個div。第二個參數是咱們的配置項。下面會詳細介紹,第三個nodes就是咱們須要顯示的數據,實際項目中通常都是後臺返回的json.node
上面展現的功能用到了樹的左鍵點擊,郵件點擊,拖拽3個大的功能點。這裏是我項目中寫的setting的內容jquery
1 var setting = { 2 callback : { 3 onClick : zTreeOnClick, 4 onRightClick : zTreeOnRightClick, 5 beforeDrag : zTreeBeforeDrag, 6 beforeDrop : zTreeBeforeDrop, 7 onDrop : zTreeOnDrop,// 若是對象目標不是節點,不會觸發beforeDrop,直接觸發onDrop 8 }, 9 data : { 10 simpleData : { 11 enable : true, 12 idKey : "id", 13 pIdKey : "pId", 14 }, 15 key : { 16 name : "sname" 17 }, 18 keep : { 19 parent : true,//沒有子節點也保持父節點狀態 20 leaf : false 21 } 22 }, 23 edit : { 24 enable : true, 25 showRemoveBtn : false, 26 showRenameBtn : false, 27 drag : { 28 isCopy : false,//拖拽節點不是複製 29 isMove : true,//拖拽節點只是移動 30 prev : true,//能夠放到節點前面 31 next : true,//能夠放到其餘節點後面 32 inner : canInner//可否放到節點裏面看回調函數返回的值 33 } 34 }, 35 view : { 36 selectedMulti : false 37 } 38 };
這裏經常使用到的左鍵點擊事件什麼的這裏就不提了,能夠參照官網的例子。這裏就記錄下onRightClick事件和onDrop事件。數據庫
首先是onRightClick事件,彈出右鍵菜單欄,而後點擊不一樣的節點郵件的菜單欄仍是不一樣的。點擊菜單欄上的不一樣的選項觸發不一樣的事件。首先咱們要讓右鍵樹節點在相應的地方產生菜單。不過不用急,這裏ztree給咱們返回的參數中包含了標準的event,右鍵點擊的節點node,還有點擊tree的Id(若是一個頁面中有多棵樹,這個參數就顯得十分重要,若是就一個樹,那麼這個參數就沒什麼多大的做用)。咱們能夠經過event來肯定鼠標在頁面中具體的位置,而後根據node來判斷右鍵菜單的詳細內容和相關的綁定事件。下面是項目中的代碼:json
1 // 右鍵菜單功能 2 function zTreeOnRightClick(event, treeId, treeNode) { 3 $('#rightMenu').remove();// 移出以前的右鍵菜單,若是有; 4 if (treeNode) { 5 zTreeObj.selectNode(treeNode); 6 var isEqu = treeNode.isEqu ? true : false, isEquHtml = ""; 7 if (!isEqu) { 8 isEquHtml = "<li id='addDep'>添加部門</li>" 9 + "<li id='addEqu'>添加設備</li>"; 10 } 11 var editName = isEqu ? "修改設備" : "修改部門"; 12 var deleteName = isEqu ? "刪除設備" : "刪除部門"; 13 var html = "<ul id='rightMenu'>" + isEquHtml + "<li id='edit'>" 14 + editName + "</li>" + "<li id='delete'>" + deleteName 15 + "</li>" + +"</ul>"; 16 var menu = $(html).css({ 17 left : event.pageX + 5 + 'px', 18 top : event.pageY + 5 + 'px' 19 }); 20 $('body').append(menu); 21 menuClick();// 給添加的元素綁定事件 22 } 23 }
我這邊的實際狀況是看樹上的節點中是否有isEqu屬性。若是含有這個屬性則證實是設備節點,那麼就只有修改設備和刪除設備2個功能。若是沒有,那麼就證實這個是部門或者公司節點,那麼就有添加設備,添加部門,刪除設備和刪除部門的功能。而後經過jquery的css函數來肯定菜單彈出的具體位置。其餘的css能夠提早在頁面中寫好,好比說hover事件和菜單的樣式。在代碼中只要控制菜單的left和top屬性就好了。這裏值得一提的是,咱們給菜單綁定的事件menuClick函數每次都須要在菜單添加的時候運行而不是在$(function(){})中,由於這裏的菜單自己是不存在body中的,是右鍵點擊的時候動態生成的,而後點擊之後又移除了,因此每次生成的時候都須要給這個菜單綁定相關的點擊事件。詳細的點擊事件這裏就很少展開敘述了。bootstrap
接下來是拖拽事件。值得一提的是這個beforeDrag和beforeDrop這兩個幾戶如出一轍的回調函數,當時沒注意被搞懵逼了。beforeDrag是拖拽前調用的,beforeDrop是拖拽結束前調用的回調。其原理就是鼠標的mousedown和mouseup還有一個dragflag(拖拽的標誌)。我這裏總公司這個節點是不能移動的,因此在beforeDrap回調裏面判斷一下節點的id,若是是0就表明是總公司,在beforeDrag中返回false就不會再調用onDrag函數了,節點就不能被拖拽。下面是項目中的代碼供參考
function zTreeBeforeDrag(treeId, treeNodes) { if (treeNodes[0].id == 0) { layer.msg('總公司目錄沒法移動!', { time : 1000 }); return false; } else { return true; } }
這裏onDrop回調調用後會自動把移動的節點move到你想要移動的地方。可是我這裏須要加一個是否移動的提示框,因此若是仍是用onDrop的話,會直接移動。由於我這裏的彈窗是異步的,js仍是會本身執行下去調用onDrop而無論beforeDrop中返回的,除非調用的是系統的comfirm函數,這個會阻塞js進程,可是樣式很差調我就放棄了,我這裏是直接在onDrop中return掉,不讓他移動節點,而是在beforeDrop中本身判斷節點是否能夠移動,而後調用ztree的moveNode方法本身移動節點。下面是相關代碼
1 // 拖拽子節點判斷 2 function canInner(treeId, treeNodes, targetNode) { 3 return (targetNode && !targetNode.isEqu); 4 } 5 // 拖拽前的判斷 6 function zTreeBeforeDrop(treeId, treeNodes, targetNode, moveType) { 7 var msg = '是否將 [' + treeNodes[0].sname + '] 移動到 [' + targetNode.sname; 8 switch (moveType) { 9 case 'inner': 10 msg += ' ]以內?'; 11 break; 12 case 'prev': 13 msg += ' ]以前?'; 14 break; 15 case 'next': 16 msg += ' ]以後?'; 17 default: 18 break; 19 } 20 layer.confirm(msg, function(index) { 21 zTreeObj.moveNode(targetNode, treeNodes[0], moveType); 22 layer.close(index); 23 }); 24 return false; 25 } 26 // 拖拽結束 27 function zTreeOnDrop(event, treeId, treeNodes, targetNode, moveType) { 28 if (!targetNode) { 29 layer.msg('目標對象無效!', { 30 time : 1000 31 }); 32 return; 33 } 34 }
上面代碼僅僅用onDrop函數來提示用戶移動到的節點是無效的這個功能而已,其餘功能都是在beforeDrop中實現的。到這裏忘記介紹了nodes這個屬性。咱們通常會在setting.data中啓用simpleData,這樣的話咱們能夠直接設置id和pid2個參數來肯定上下級的關係,而不須要嵌套用children這個屬性來肯定上下級的關係,這樣的話後臺返回的數據就直接從數據庫中取出返回一個List的類型就行而不須要轉化成複雜的嵌套模式,這個仍是挺好用的。下面是我用到的展現的nodes:
1 var zNodes = [ { 2 sname : '總公司', 3 id : 0, 4 pId : -1, 5 open : true, 6 isParent : true 7 }, { 8 sname : '技術中心', 9 id : 1, 10 pId : 0, 11 open : true, 12 isParent : true 13 }, { 14 sname : '生產中心', 15 id : 2, 16 pId : 0, 17 open : true, 18 isParent : true 19 }, { 20 sname : '物流中心', 21 id : 3, 22 pId : 0, 23 open : true, 24 isParent : true 25 }, { 26 sname : '設備1', 27 id : 4, 28 pId : 1, 29 isEqu : true, 30 31 }, { 32 sname : '設備2', 33 id : 5, 34 pId : 1, 35 isEqu : true, 36 37 }, { 38 sname : '設備3', 39 id : 6, 40 pId : 2, 41 isEqu : true, 42 }, { 43 sname : '設備4', 44 id : 7, 45 pId : 3, 46 isEqu : true, 47 }, ];
今天這裏的記錄就差很少到這裏了,具體的api仍是能夠參考官網的。並且官網的教程也很詳細,這裏就很少介紹了,哈哈(真的不是我懶哦)~