0 zTree簡介
樹形控件的使用是應用開發過程中必不可少的。zTree 是一個依靠 jQuery 實現的多功能 “樹插件”。優異的性能、靈活的配置、多種功能的組合是 zTree 最大優點。
0.0 zTree的特點
•最新版的zTree將核心代碼按照功能進行了分割,不需要的代碼可以不用加載,如普通使用只需要加載核心的jquery.ztree.core-3.5.js,需要使用勾選功能加載jquery.ztree.excheck-3.5.min.js,需要使用編輯功能加載jquery.ztree.exedit-3.5.min.js
•采用了延遲加載技術,上萬節點輕松加載,即使在 IE6 下也能基本做到秒殺
•兼容 IE、FireFox、Chrome、Opera、Safari 等瀏覽器
•支持 JSON 數據
•支持靜態 和 Ajax 異步加載節點數據
•支持任意更換皮膚 / 自定義圖標(依靠css)
•支持極其靈活的 checkbox 或 radio 選擇功能
•提供多種事件響應回調
•靈活的編輯(增/刪/改/查)功能,可隨意拖拽節點,還可以多節點拖拽
•在一個頁面內可同時生成多個 Tree 實例
•簡單的參數配置實現,靈活多變的功能
0.1 zTree文件介紹
從zTree官網下載的zTree包括以下組成部分

•metroStyle文件夾:zTree的metro風格樣式相關文件(圖片及css樣式表)。
•zTreeStyle文件夾:zTree的標准風格樣式文件夾(圖片及css樣式表)
•js文件:zTree.all.js是完整的js庫,可單純加載此文件實現所有zTree功能,ztree.core、ztree.excheck、ztree.exedit、ztree.exhide是對ztree按照功能進行的分割,分別對應基本功能、復選功能、編輯功能、顯隱功能。
1 zTree的基本使用
1.0 zTree的創建
在頁面中添加對zTree的js及css引用,由於zTree基於JQuery,JQuery的引用是必須的。
<!DOCTYPE html>
<HTML>
<HEAD>
<TITLE> ZTREE DEMO </TITLE>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript" src="jquery.ztree.core-3.x.js"></script>
<SCRIPT LANGUAGE="JavaScript">
var zTreeObj;
var setting = {}; // zTree 的參數配置,后面詳解
var zNodes = [ // zTree 的數據屬性,此處使用標准json格式
{
name: "test1", open: true, children: [
{ name: "test1_1" }, { name: "test1_2" }]
},
{
name: "test2", open: true, children: [
{ name: "test2_1" }, { name: "test2_2" }]
}
];
$(document).ready(function () {
zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes); //初始化zTree,三個參數一次分別是容器(zTree 的容器 className 別忘了設置為 "ztree")、參數配置、數據源
});
</SCRIPT>
</HEAD>
<BODY>
<div>
<ul id="treeDemo" class="ztree"></ul>
</div>
</BODY>
</HTML>
運行結果如下
1.1 zTree的配置
zTree的配置采用Json格式,按照配置的類型分為view(可視界面相關配置)、data(數據相關配置)、check(復選框相關配置)、callback(各類事件的回調函數配置)、async(zTree異步加載配置),一下是我們經常會使用到的一些配置及說明,其他詳細配置可以參考zTree官方API文檔的詳細介紹。
var setting = {
view: {
selectedMulti: true, //設置是否能夠同時選中多個節點
showIcon: true, //設置是否顯示節點圖標
showLine: true, //設置是否顯示節點與節點之間的連線
showTitle: true, //設置是否顯示節點的title提示信息
},
data: {
simpleData: {
enable: false, //設置是否啟用簡單數據格式(zTree支持標准數據格式跟簡單數據格式,上面例子中是標准數據格式)
idKey: "id", //設置啟用簡單數據格式時id對應的屬性名稱
pidKey: "pId" //設置啟用簡單數據格式時parentId對應的屬性名稱,ztree根據id及pid層級關系構建樹結構
}
},
check:{
enable: true //設置是否顯示checkbox復選框
},
callback: {
onClick: onClick, //定義節點單擊事件回調函數
onRightClick: OnRightClick, //定義節點右鍵單擊事件回調函數
beforeRename: beforeRename, //定義節點重新編輯成功前回調函數,一般用於節點編輯時判斷輸入的節點名稱是否合法
onDblClick: onDblClick, //定義節點雙擊事件回調函數
onCheck: onCheck //定義節點復選框選中或取消選中事件的回調函數
},
async: {
enable: true, //設置啟用異步加載
type: "get", //異步加載類型:post和get
contentType: "application/json", //定義ajax提交參數的參數類型,一般為json格式
url: "/Design/Get", //定義數據請求路徑
autoParam: ["id=id", "name=name"] //定義提交時參數的名稱,=號前面標識節點屬性,后面標識提交時json數據中參數的名稱
}
};
需要注意的是,zTree的事件回調部分,基本上每一個事件都對應一個beforeXXX事件,比如onClick事件對應有一個beforeOnClick事件,主要用於控制相關事件是否允許執行,如果before事件返回false,則取消執行對應相關事件。
1.2 zTree的數據格式
zTree的每一個節點都是一個treeNode對象,treeNode對象經常用到的屬性和方法如下:
treeNode: {
name, //節點顯示的文本
checked, //節點是否勾選,ztree配置啟用復選框時有效
open, //節點是否展開
icon, //節點的圖標
iconOpen, //節點展開式的圖標
iconClose, //節點折疊時的圖標
id, //節點的標識屬性,對應的是啟用簡單數據格式時idKey對應的屬性名,並不一定是id,如果setting中定義的idKey:"zId",那么此處就是zId
pId, //節點parentId屬性,命名規則同id
children, //得到該節點所有孩子節點,直接下級,若要得到所有下屬層級節點,需要自己寫遞歸得到
isParent, //判斷該節點是否是父節點,一般應用中通常需要判斷只有葉子節點才能進行相關操作,或者刪除時判斷下面是有子節點時經常用到。
getPath() //得到該節點的路徑,即所有父節點,包括自己,此方法返回的是一個數組,通常用於創建類似面包屑導航的東西A-->B-->C
}
zTree的數據源一般有標准數據格式、簡單數據格式兩種,標准數據格式通過指定節點的chidren屬性構建層級關系,而簡單數據格式根據根據id,pid屬性構建層級關系,我們在應用開發中使用關系型數據庫,一般采用的都是簡單數據格式。
標准數據格式
var nodes = [
{name: "父節點1", children: [
{name: "子節點1"},
{name: "子節點2"}
]}
];
簡單數據格式
var nodes = [
{id:1, pId:0, name: "父節點1"},
{id:11, pId:1, name: "子節點1"},
{id:12, pId:1, name: "子節點2"}
];
注意zTree的默認配置是不啟用簡單數據格式,使用簡單數據格式一定要在setting中進行簡單數據格式的相關配置。
1.3 zTree的常用方法
zTree的主要操作方法介紹如下
獲取zTree對象:var treeObj = $.fn.zTree.getZTreeObj("tree");
增加節點:addNodes(parentNode,index,newNodes,isSlient)
parentNode:指定的父節點,如果增加根節點,請設置 parentNode 為 null 即可
index:新節點插入的位置(從 0 開始),index = -1 時,插入到最后,此參數可忽略
newNodes:需要增加的節點數據 JSON 對象集合,數據只需要滿足 zTree 的節點數據必需的屬性即可
isSilent:true 時,添加節點后不展開父節點,其他值或缺省狀態都自動展開
勾選或取消勾選全部節點:checkAllNodes(checked);
checked參數為true時全部勾選,為false時全部取消勾選。
勾選或取消勾選單個節點:checkNode(node, checked, checkedTypeFlag,callbackFlag);
node:要進行操作的節點
checked:為true勾選,為false取消勾選
checkeTypeFlag:為true表示對當前結點的子節點及父節點進行勾選狀態的聯動,為false不聯動
callbackFlag:為true時表示執行beforeOnCheck和onCheck事件的回調函數,為false不執行
編輯節點
edit(node); 使節點處於編輯狀態,必須引用jquery.ztree.exedit 擴展。
展開或折疊全部節點:expandAll(expand);
expand為true是展開所有節點,為false是折疊所有節點。
根據節點屬性查找結點:getNodesByParam(key,value, parentNode);
key:屬性名
value:屬性值
parentNode:是否在指定節點下查找,為null表示整個樹查找。
獲取被勾選或未被勾選的節點集合:getCheckedNodes(checked);
checked為true表示獲取所有被勾選的節點集合,為false表示所有未被勾選的節點集合
獲取輸入框勾選狀態被改變的節點集合:getChangeCheckedNodes()
2 zTree的常用操作
2.0 ajax請求數據並創建zTree
$(function () {
var setting = { //此處根據自己需要進行配置
view: {
selectedMulti: false
},
data: {
simpleData: {
enable: true
}
},
callback: {
onClick: onDesignTreeClick,
onRightClick: OnRightClick,
beforeRename: beforeRename, onCheck:onCheck
}
};
$.ajax({
type: "Get",
url: "/Design/GetDesignTreeData", //ajax請求地址
success: function (data) {
$.fn.zTree.init($("#treeZo"), setting, data); //加載數據
},
});
});
后台代碼如下,可以根據需要返回你想要的任何數據,綁定到zTree上,然后通過treeNode.屬性名取到對應的值,實現一些界面邏輯操作。
public ActionResult GetDesignTreeData()
{
var result = _designAppService.GetDesignTreeData();
List<ModelTreeViewModel> treeModels = new List<ModelTreeViewModel>();
bool open = false;
foreach (var design in result.Designs)
{
if (design.ParentId == Guid.Empty)
open = true;
else open = false;
treeModels.Add(new ModelTreeViewModel() { Id = design.Id.ToString(), PId = design.ParentId.ToString(), Name = design.Name, Open = open, Data = design.Remarks ?? "", ViewPoint = design.ViewPoint ?? "", Checked = true });
}
return Json(treeModels, JsonRequestBehavior.AllowGet);
}
2.1 節點單擊操作
節點單擊事件會捕獲事件對象e,zTree的唯一標識treeId,當前選中的節點對象treeNode三個參數。根據實際需求可獲取treeNode中包含的任何屬性數據,進行相關操作
function onClick(e, treeId, treeNode) {
if (treeNode.isParent) //如果不是葉子結點,結束
return;
alert(treeNode.name); //獲取當前結點上的相關屬性數據,執行相關邏輯
};
2.2 節點復選框事件
一般情況下我們會直接使用treeObj.getCheckedNodes(true);獲取所有選中的節點,然后遍歷所有選中的節點進行相關操作,當面對大數據量時,這種操作方法便不可取,可通過getChangeCheckedNodes()方法獲取勾選狀態被改變的節點集合,值針對狀態改變的節點做相應處理。
function onCheck() {
var treeObj = $.fn.zTree.getZTreeObj("treeDemo"); //獲取樹對象
var nodes = treeObj.getChangeCheckedNodes(); //獲取勾選狀態改變的節點
var designIds = [];
var status = 0; //定義初始勾選狀態為未勾選
if (nodes[0].checked)
status = 1; //如果狀態改變節點為勾選狀態,說明當前操作是從未勾選變為已勾選。
$.each(nodes, function (i, item) {
designIds.push(item.id); //將狀態改變的節點id輸出到數組
item.checkedOld = item.checked; //這句話很關鍵,將節點的初始狀態置為當前狀態。否則每次勾選操作獲取狀態改變節點時只會跟樹初始化的狀態相比較。
})
$.ajax({
type: "Post",
url: "/Design/GetRelationComponentIdsByDesigns",
data: { "designIds": designIds },
success: function (data) {
RealBimOcx.BatchAddSubClrInfoBegin();
$.each(data.result, function (i, item) {
if (status == 1) //這里根據發生改變的節點是勾選還是為勾選進行相關邏輯操作。
RealBimOcx.AddSubClrInfo(item, 255, 255, 0);
else
RealBimOcx.AddSubClrInfo(item, 0, 255, 0);
if (i % 100 == 0) {
RealBimOcx.BatchAddSubClrInfoEnd();
RealBimOcx.BatchAddSubClrInfoBegin();
}
})
RealBimOcx.BatchAddSubClrInfoEnd();
}
})
};
2.3 實現zTree的右鍵增刪改操作
首先定義右鍵彈出面板
<div id="rMenu" style="z-index:100;"> <ul> <li id="m_add" onclick="addTreeNode();">新增節點</li> <li id="m_del" onclick="removeTreeNode();">刪除節點</li> <li id="m_edit" onclick="editTreeNode();" style="border-bottom:1px solid #cecece">編輯節點</li><li id="m_left">升級</li> <li id="m_right">降級</li> <li id="m_up">上移</li> <li id="m_down" style="border-bottom:1px solid #cecece">下移</li> <li id="m_reset" onclick="resetTree();">重置節點</li> <li id="m_open" onclick="treeOpen()">展開所有</li> <li id="m_stop" onclick="treeStop()">收起所有</li> </ul> </div>

實現zTree右鍵單擊事件回調函數
//右鍵單擊回調函數
function OnRightClick(event, treeId, treeNode) {
$("#treeZo").hide();
if (!treeNode && event.target.tagName.toLowerCase() != "button" && $(event.target).parents("a").length == 0) {
zTree.cancelSelectedNode();
showRMenu("root", event.clientX, event.clientY); //根據鼠標位置顯示右鍵操作面板
} else if (treeNode && !treeNode.noR) {
zTree.selectNode(treeNode);
showRMenu("node", event.clientX, event.clientY);
}
$("#treeZo").show();
}
//根據節點類型,控制右鍵操作菜單哪些可用哪些不可用
function showRMenu(type, x, y) {
$("#rMenu ul").show();
if (type == "root") {
$("#m_del").hide();
$("#m_edit").hide();
$("#m_left").hide();
$("#m_right").hide();
$("#m_up").hide();
$("#m_down").hide();
$("#m_add").addClass('mboder');
} else {
$("#m_del").show();
$("#m_edit").show();
$("#m_left").show();
$("#m_right").show();
$("#m_up").show();
$("#m_down").show();
$("#m_add").removeClass('mboder');
}
rMenu.css({ "top": y + "px", "left": x + "px", "visibility": "visible" });
$("body").bind("mousedown", onBodyMouseDown);
}
//以藏右鍵面板
function hideRMenu() {
if (rMenu) rMenu.css({ "visibility": "hidden" });
$("body").unbind("mousedown", onBodyMouseDown);
}
//單擊頁面其他位置 隱藏右鍵面板
function onBodyMouseDown(event) {
if (!(event.target.id == "rMenu" || $(event.target).parents("#rMenu").length > 0)) {
rMenu.css({ "visibility": "hidden" });
}
}
新增節點
//增加節點
function addTreeNode() {
hideRMenu();
var name = new Date().getTime(); //利用時間戳生成節點名稱,保證節點名稱唯一
var newNode = {
name: name
};
if (zTree.getSelectedNodes()[0]) {
newNode.checked = zTree.getSelectedNodes()[0].checked;
newNode.pid = zTree.getSelectedNodes()[0].id;
zTree.addNodes(zTree.getSelectedNodes()[0], newNode);
} else {
zTree.addNodes(null, newNode);
}
var node = zTree.getNodeByParam("name", name, null); //得到新增加的節點
zTree.selectNode(node); //選中新增加的節點
zTree.editName(node); //讓新增加的節點處於編輯狀態
}
編輯節點
function editTreeNode() {
var nodes = zTree.getSelectedNodes(); //得到選中節點集合
if (nodes && nodes.length > 0) {
var parent = nodes[0].getParentNode(); //得到選中節點的父節點
if (parent) {
nodes[0].pid = parent.id; //如果選中節點父節點存在,將當前結點的pid屬性值設置為父節點的id
}
zTree.editName(nodes[0]); //讓選中節點處於編輯狀態
}
hideRMenu(); //隱藏右鍵面板
};
節點編輯狀態離開時觸發事件
//編輯並保存節點
function beforeRename(treeId, treeNode, newName, isCancel) {
if (newName.length == 0) { //節點名稱判斷
alert("不能為空。");
return false;
}
else {
$.ajax({ //數據入庫
type: "Post",
url: "/Design/InsertOrUpdate",
data: { "dto": { "Id": treeNode.id, "ParentId": treeNode.pid, "Name": newName } },
succes: function (data) {
if (data.result == "Faild") {
layerAlert("保存失敗。");
return false;
}
else {
treeNode.id = data.result; //將返回的id賦值給當前結點
return true;
}
}
});
}
};
刪除節點數據
function removeTreeNode() {
hideRMenu();
var nodes = zTree.getSelectedNodes();
if (nodes && nodes.length > 0) {
if (nodes[0].children && nodes[0].children.length > 0) {
alert("包含下級,無法刪除。");
} else {
if (confirm("該操作會將關聯數據同步刪除,是否確認刪除?") == true) {
$.ajax({
type: "Post",
url: "/Design/Delete",
data: { "id": nodes[0].id },
success: function (data) {
if (data.result == "Success") {
zTree.removeNode(nodes[0]);
}
else {
alert("刪除失敗。");
}
}
});
};
}
}
};
2.4 一些總結
我們通常使用到樹形控件做授權或關聯類似的操作,一般會先全部取消勾選,然后根據選中的數據關聯對樹控件的復選框進行選中操作,在大數據量時,大約幾萬條數據,全部取消勾選+根據關聯數據勾選相關節點這個操作通過js執行會很慢,這種情況建議在后台通過關聯關系重新組織zTree需要的數據源,對每條數據(對應樹節點)設置checked屬性,然后再前台頁面重新加載樹,這種操作速度要快得多。
$.ajax({
type: "Get",
url: "/Model/GetRelationModelTreeData?designId=" + treeNode.id + "&t=" + new Date(),
success: function (data) {
//$.each(data.result, function (i, item) {
// var node = modelTree.getNodeByParam("id", item, null);
// modelTree.checkNode(node, true, true);
//});
$.fn.zTree.init($("#treejian"), setting1, data.result); //改為重新加載,比js循環勾選速度要快。
}
});
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
