Web 項目或多或少都會有涉及到什麼人員職稱樹,菜單樹,組織機構樹...... 歷手三四個項目有大有小,採用的樹前端都是 Ztree。 有些優秀的J2EE 框架將這些常用的組件都封裝起來,作為模塊化的組件提供給前端,這樣固然是好,開發效率會提升幾倍。 客戶需求是什麼,組件化往上一套,幾分鐘就能搭建起
Web 項目或多或少都會有涉及到什麼人員職稱樹,菜單樹,組織機構樹......
歷手三四個項目有大有小,採用的樹前端都是 Ztree。
有些優秀的J2EE 框架將這些常用的組件都封裝起來,作為模塊化的組件提供給前端,這樣固然是好,開發效率會提升幾倍。
客戶需求是什麼,組件化往上一套,幾分鐘就能搭建起來。
但這樣咱程式員真的就是搬磚的了,純純的重覆性工作。
1. Ztree 主要的特點
- ZTree v3.0 將核心代碼按照功能進行了分割,不需要的代碼可以不用載入
- 採用了 延遲載入 技術,上萬節點輕鬆載入,即使在 IE6 下也能基本做到秒殺
- 相容 IE、FireFox、Chrome、Opera、Safari 等瀏覽器
- 支持 JSON 數據
- 支持靜態 和 Ajax 非同步載入節點數據
- 支持任意更換皮膚 / 自定義圖標(依靠css)
- 支持極其靈活的 checkbox 或 radio 選擇功能
- 提供多種事件響應回調
- 靈活的編輯(增/刪/改/查)功能,可隨意拖拽節點,還可以多節點拖拽喲
- 在一個頁面內可同時生成多個 Tree 實例
- 簡單的參數配置實現 靈活多變的功能
詳細的介紹請移步到Ztree官網:
http://www.ztree.me/v3/main.php#_zTreeInfo
2. Web 前端
具體使用框架不同,前端通信請求寫法可能會有差距,但無論經歷怎樣的封裝與變化,個人認為前端到後端通信方式大致為 Ajax/Websocket。
首先頁面需要引入JS,ZTree 依賴與 JQuery,所以 JQuery 寫到前面位置。
<script type="text/javascript" src='/style/js/jquery.js'></script> <script type="text/javascript" src='/style/js/jquery.ztree.core-3.5.js'></script>
其次按照項目需求不同可以進行具體配置。 zTree 配置屬性和初始化方法參照:http://www.ztree.me/v3/api.php
var setting = { view : { showLine : true, selectedMulti : false, dblClickExpand : false }, data : { simpleData : { enable : true } }, callback : { onNodeCreated : this.onNodeCreated, onClick : this.onClick } }; $.ajax({ url : 'service/Menu/getMenutree', dataType : 'json', contenttype : "application/x-www-form-urlencoded;charset=utf-8", type : 'POST', success : function(data) { if (data.success) { $.fn.zTree.init($("#treeDemo"), setting, data.returnvalue); } else { alert("載入菜單樹出錯1!"); } }, error : function(data) { alert("載入菜單樹出錯2"); } });
最後將後端組織好的 Json 數據初始化入ZTree 即可,具體的 ZTree 使用,比如顯示的樣式,拖拽,點擊事件的響應........都是支持的,看具體需求來實現。
3. Web 後端
前端的各種樣式事件響應需要一顆細膩的心,如果你們公司前後端是嚴格分工開發的,你完全可以交給前端MM了,專註後端設計。
下麵都為個人理解設計,如看客老爺有更好方式,請斧正。
首先你得需要一個像 Ztree 樹節點屬性類似的數據結構 POJO(setter,getter 方法已省略)。
其中只對幾個常用的屬性進行了定義,方便其他人使用,降低業務代碼之間的耦合性。
public class ZTreeNode{ private static final long serialVersionUID = 8732537724623459243L; private Long id; private Long pId; private String name; private Boolean open; private Boolean checked; private Boolean nocheck; private boolean cancheck; @Override public int compareTo(TreeStuffBean o) { // TODO Auto-generated method stub return 0; } }
其次你需要一張具有上下級關係的數據表,下麵這是俺自己的測試腳本。
SQL 無國界,儘管拿去練手吧。
--菜單目錄結構表 create table tb_menu( id number(10) not null, --主鍵id title varchar2(50), --標題 parent number(10) --parent id ); commit; --父菜單 insert into tb_menu(id, title, parent) values(1, '父菜單1',-1); insert into tb_menu(id, title, parent) values(2, '父菜單2',-1); insert into tb_menu(id, title, parent) values(3, '父菜單3',-1); insert into tb_menu(id, title, parent) values(4, '父菜單4',-1); insert into tb_menu(id, title, parent) values(5, '父菜單5',-1); --一級菜單 insert into tb_menu(id, title, parent) values(6, '一級菜單6',1); insert into tb_menu(id, title, parent) values(7, '一級菜單7',1); insert into tb_menu(id, title, parent) values(8, '一級菜單8',1); insert into tb_menu(id, title, parent) values(9, '一級菜單9',2); insert into tb_menu(id, title, parent) values(10, '一級菜單10',2); insert into tb_menu(id, title, parent) values(11, '一級菜單11',2); insert into tb_menu(id, title, parent) values(12, '一級菜單12',3); insert into tb_menu(id, title, parent) values(13, '一級菜單13',3); insert into tb_menu(id, title, parent) values(14, '一級菜單14',3); insert into tb_menu(id, title, parent) values(15, '一級菜單15',4); insert into tb_menu(id, title, parent) values(16, '一級菜單16',4); insert into tb_menu(id, title, parent) values(17, '一級菜單17',4); insert into tb_menu(id, title, parent) values(18, '一級菜單18',5); insert into tb_menu(id, title, parent) values(19, '一級菜單19',5); insert into tb_menu(id, title, parent) values(20, '一級菜單20',5); --二級菜單 insert into tb_menu(id, title, parent) values(21, '二級菜單21',6); insert into tb_menu(id, title, parent) values(22, '二級菜單22',6); insert into tb_menu(id, title, parent) values(23, '二級菜單23',7); insert into tb_menu(id, title, parent) values(24, '二級菜單24',7); insert into tb_menu(id, title, parent) values(25, '二級菜單25',8); insert into tb_menu(id, title, parent) values(26, '二級菜單26',9); insert into tb_menu(id, title, parent) values(27, '二級菜單27',10); insert into tb_menu(id, title, parent) values(28, '二級菜單28',11); insert into tb_menu(id, title, parent) values(29, '二級菜單29',12); insert into tb_menu(id, title, parent) values(30, '二級菜單30',13); insert into tb_menu(id, title, parent) values(31, '二級菜單31',14); insert into tb_menu(id, title, parent) values(32, '二級菜單32',15); insert into tb_menu(id, title, parent) values(33, '二級菜單33',16); insert into tb_menu(id, title, parent) values(34, '二級菜單34',17); insert into tb_menu(id, title, parent) values(35, '二級菜單35',18); insert into tb_menu(id, title, parent) values(36, '二級菜單36',19); insert into tb_menu(id, title, parent) values(37, '二級菜單37',20); --三級菜單 insert into tb_menu(id, title, parent) values(38, '三級菜單38',21); insert into tb_menu(id, title, parent) values(39, '三級菜單39',22); insert into tb_menu(id, title, parent) values(40, '三級菜單40',23); insert into tb_menu(id, title, parent) values(41, '三級菜單41',24); insert into tb_menu(id, title, parent) values(42, '三級菜單42',25); insert into tb_menu(id, title, parent) values(43, '三級菜單43',26); insert into tb_menu(id, title, parent) values(44, '三級菜單44',27); insert into tb_menu(id, title, parent) values(45, '三級菜單45',28); insert into tb_menu(id, title, parent) values(46, '三級菜單46',28); insert into tb_menu(id, title, parent) values(47, '三級菜單47',29); insert into tb_menu(id, title, parent) values(48, '三級菜單48',30); insert into tb_menu(id, title, parent) values(49, '三級菜單49',31); insert into tb_menu(id, title, parent) values(50, '三級菜單50',31); commit;TB_MENU
當然對於業務 POJO 的數據結構封裝比不可少,主流的持久層框架都能將表映射為 POJO對象,有自動生成業務介面,服務層的。
不用那些看起來難懂的書面話, 個人理解 POJO 的作用,將現實業務抽象到程式表現層。
public class TbMenu { private Long id; private String title; private Long parent; }TbMenu
最後是核心的業務處理邏輯,通過持久層獲取想要遍歷的數據,進行處理封裝。
Map<String, Object> returnvalue = new HashMap<>(); List<TbMenu> menuList = dataDao.find(TbMenu.class); List<ZTreeNode> ZTreeNodeList = new ArrayList<>(); ZTreeNode treeNode; for (TbMenu tbMenu : menuList) { treeNode = new ZTreeNode(); treeNode.setId(tbMenu.getId()); treeNode.setpId(tbMenu.getParent()); treeNode.setName(tbMenu.getTitle()); ZTreeNodeList.add(treeNode); } treeNode = new ZTreeNode(); treeNode.setId(-1L); treeNode.setpId(0L); treeNode.setName("菜單樹"); treeNode.setOpen(true); ZTreeNodeList.add(0, treeNode); TreeComparator treeComparator = new TreeComparator(); Collections.sort(ZTreeNodeList, treeComparator);
需要註意的地方是最後在 ZTreeNodeList 頭部添加的 treeNode 為樹組件的頭部,這裡需要將數據表中的一級菜單的 parentid 設置為 -1。
最終界面展示