ztree封裝的樹結構vue組件

先來一張效果圖:

1.z-tree插件下載地址http://www.treejs.cn/v3/main.php#_zTreeInfo

2.下載完成後將插件放到項目裏在mian.js裏面引入即可

//main.js中引入

import './plugins/zTree/jquery.ztree.all.js'
import './plugins/zTree/jquery.ztree.core.js'
import './plugins/zTree/jquery.ztree.excheck.js'
import './plugins/zTree/jquery.ztree.exedit.js'
import './plugins/zTree/jquery.ztree.exhide.js'

3.ztree組件內部代碼

<template>
    <div id="areaTree">
		<div class="addnode" v-if="addtype!=false"></div>
        <div class="boxtitle">
			<el-input
				id="key"
				size="mini"
				placeholder="請輸入內容"
				suffix-icon="el-icon-search"
				v-model="inputval">
			</el-input>
			<el-button type="primary" size="mini" title="刷新" icon="el-icon-refresh" @click="shauxin"></el-button>
			<el-button type="primary" size="mini" v-if="addtype===false?addtype:addtype1" title="添加根目錄" icon="el-icon-plus" @click="addzTreeOne"></el-button>
        </div>
        <div class="tree-box">
            <div class="zTreeDemoBackground left">
                <ul id="treeDemo" class="ztree"></ul>
            </div>
        </div>
    </div>
</template>

<script>
// import fuzzysearch from "@/plugins/fuzzysearch.js";
export default {
    name: 'ztree',
    data () {
        return {
			inputval: '',
			prid: '',
			ztreedata: '',
			addtype1: true,
			addchild1: true
        }
	},
	props: ['treedata','addtype','addchild'],
    components: {
	},
	watch: {
		immediate: true,
		treedata(newval, oldval) {
			this.ztreedata = newval;
			this.szTree();
		}
	},
    created() {

    },
    mounted() {
		this.szTree();
    },
    methods: {
		shauxin() {
			this.$emit('shuaxin')
		},
		szTree: function(iname) {
			var setting = {
				view: {
					addHoverDom: this.addtype===false||this.addchild===false?false:this.addHoverDom,
					removeHoverDom: this.removeHoverDom,
					selectedMulti: false,
					addDiyDom: this.addDiyDom,
					// showIcon: false,
					showLine: true,
				},
				edit: {
					enable:  this.addtype===false?false:true,
					// showRenameBtn: true,
					renameTitle: "編輯目錄名稱",
					removeTitle: "刪除目錄",
					drag: {
						prev: this.canPrev,
						next: this.canNext,
						inner: true
					}

				},
				callback: {
					onClick: this.zTreeOnClick,
					beforeDrag: this.beforeDrag,
					beforeDrop: this.beforeDrop, //用於捕獲節點拖拽操作結束之前的事件回調函數
					onNodeCreated: this.zTreeOnNodeCreated, //改圖標
					beforeEditName: this.zTreeBeforeRename, //編輯節點
					beforeRemove: this.zTreeBeforeRemove //刪除節點
				},
				data: {
					key:{
						name:"catalogName"
					},
					simpleData: {
						enable: true,
						idKey : "dataSourceGroupId",
						pIdKey : "parentDSource",
						rootPId : null
					}
				},
			};
			$.fn.zTree.init($("#treeDemo"), setting, this.ztreedata);
			this.fuzzySearch('treeDemo', '#key', null, true); //初始化模糊搜索方法
		},
		// 劃過顯示添加節點
		addHoverDom: function(treeId, treeNode) {
			var _this = this;
			// console.log(treeNode)
			// if(treeNode.parentDSource!=null) {
			// 	$("#" + treeId + " .button.edit").hide();
			// 	$("#" + treeId + " .button.remove").hide();
			// }
			// 判斷是數據源子節點隱藏增修改圖標
			if (treeNode.type == 0) {
				$("#" + treeId + " .button.add").hide(); //隱藏添加圖標
				$("#" + treeId + " .button.edit").hide();
				$("#" + treeId + " .button.remove").hide();
			} else {
				//添加目錄
				var sObj = $("#" + treeNode.tId + "_span");
				if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return;
				var addStr = "<span class='button add' id='addBtn_" + treeNode.tId +
					"'title='添加下級目錄' onfocus='this.blur();'></span>";
				sObj.after(addStr);    //註釋下級目錄添加
				var btn = $("#addBtn_" + treeNode.tId);
				$('.ztree li span.button.add').css({
					'margin-left': '2px',
					'margin-right': '-1px',
					'background-position': '-144px 0',
					'vertical-align': 'top',
				})
				if (btn) btn.bind("click", function() {
					_this.$emit('addtreeNode', {'treeNode': treeNode})
				});
			}
		},
		// 滑動覆蓋移除
		removeHoverDom(treeId, treeNode) {
			$("#addBtn_" + treeNode.tId).unbind().remove();
		},
		//自定義顯示內容,字數截取
		addDiyDom: function(treeId, treeNode) {
			var spantxt = $("#" + treeNode.tId + "_span").html();
		},
		//禁止拖拽到頂級節點前面的操作
		canPrev: function(treeId, nodes, targetNode) {
			console.log("targetNode", targetNode);
			var pNode = targetNode.getParentNode();
			if (pNode && pNode.dropInner === false) {
				return false;
			}
			if (!targetNode.parentDSource && nodes[0].type == 0) {
				return false;
			}
			return true;
		},
		//禁止拖拽到根節點後面的操作
		canNext: function(treeId, nodes, targetNode) {
			if (!targetNode.parentDSource && nodes[0].type == 0) {
				return false;
			}
			return true;
		},
		//拖拽之前判斷是否可拖拽
		beforeDrag: function(treeId, treeNodes) {
			return false;
			// return true;
		},
		//拖拽結束之後
		beforeDrop: function(treeId, treeNodes, targetNode, moveType) {
			console.log(targetNode);
			this.prid = treeNodes[0].parentDSource ? treeNodes[0].parentDSource : "";
			if (targetNode == null)
				return false;
			var newPrid = targetNode.dataSourceGroupId
			if (targetNode.type == 0) {
				return false;
			}
			var msid = treeNodes[0].dataSourceGroupId;
			var ypid = this.prid; //原來的父級ID
			var xpid = newPrid; //現在的父級ID
			var type = treeNodes[0].type; //類型,0是數據源,1是目錄

			if (this.prid == newPrid) {
				xpid = "";
			}
			//修改原目錄圖標
			var zTree_Menu = $.fn.zTree.getZTreeObj("treeDemo");
			var node = zTree_Menu.getNodeByParam("id", ypid);
		},
		// 編輯節點
		zTreeBeforeRename: function(treeId, treeNode, newName, isCancel) {
			this.$emit('zTreeBeforeRename',{'treeNode':treeNode});
			return false;
		},
		//刪除組
		zTreeBeforeRemove: function(treeId, treeNode) {
			this.$emit('removeTreeNode',{'treeId': treeId, 'treeNode': treeNode})
			return false;
		},
		//點擊單個節點
		zTreeOnClick: function(event, treeId, treeNode) {
			this.$emit('zTreeOnClick',{'treeNode':treeNode});
		},
		// 添加根目錄
		addzTreeOne: function(){
			this.$emit('addzTreeOne');
		},
		// 模糊查詢方法
		fuzzySearch(zTreeId, searchField, isHighLight, isExpand){
			var zTreeObj = $.fn.zTree.getZTreeObj(zTreeId);//get the ztree object by ztree id
			if(!zTreeObj){
				alert("fail to get ztree object");
			}
			var nameKey = zTreeObj.setting.data.key.name; //get the key of the node name
			isHighLight = isHighLight===false?false:true;//default true, only use false to disable highlight
			isExpand = isExpand?true:false; // not to expand in default
			zTreeObj.setting.view.nameIsHTML = isHighLight; //allow use html in node name for highlight use
			
			var metaChar = '[\\[\\]\\\\\^\\$\\.\\|\\?\\*\\+\\(\\)]'; //js meta characters
			var rexMeta = new RegExp(metaChar, 'gi');//regular expression to match meta characters
			
			// keywords filter function 
			function ztreeFilter(zTreeObj,_keywords,callBackFunc) {
				if(!_keywords){
					_keywords =''; //default blank for _keywords 
				}
				
				// function to find the matching node
				function filterFunc(node) {
					if(node && node.oldname && node.oldname.length>0){
						node[nameKey] = node.oldname; //recover oldname of the node if exist
					}
					zTreeObj.updateNode(node); //update node to for modifications take effect
					if (_keywords.length == 0) {
						//return true to show all nodes if the keyword is blank
						zTreeObj.showNode(node);
						zTreeObj.expandNode(node,isExpand);
						return true;
					}
					//transform node name and keywords to lowercase
					if (node[nameKey] && node[nameKey].toLowerCase().indexOf(_keywords.toLowerCase())!=-1) {
						if(isHighLight){ //highlight process
							//a new variable 'newKeywords' created to store the keywords information 
							//keep the parameter '_keywords' as initial and it will be used in next node
							//process the meta characters in _keywords thus the RegExp can be correctly used in str.replace
							var newKeywords = _keywords.replace(rexMeta,function(matchStr){
								//add escape character before meta characters
								return '\\' + matchStr;
							});
							node.oldname = node[nameKey]; //store the old name  
							var rexGlobal = new RegExp(newKeywords, 'gi');//'g' for global,'i' for ignore case
							//use replace(RegExp,replacement) since replace(/substr/g,replacement) cannot be used here
							node[nameKey] = node.oldname.replace(rexGlobal, function(originalText){
								//highlight the matching words in node name
								var highLightText =
									'<span style="color: whitesmoke;background-color: darkred;">'
									+ originalText
									+'</span>';
								return 	highLightText;					
							});
							zTreeObj.updateNode(node); //update node for modifications take effect
						}
						zTreeObj.showNode(node);//show node with matching keywords
						return true; //return true and show this node
					}
					
					zTreeObj.hideNode(node); // hide node that not matched
					return false; //return false for node not matched
				}
				
				var nodesShow = zTreeObj.getNodesByFilter(filterFunc); //get all nodes that would be shown
				processShowNodes(nodesShow, _keywords);//nodes should be reprocessed to show correctly
			}
			
			/**
			 * reprocess of nodes before showing
			 */
			function processShowNodes(nodesShow,_keywords){
				if(nodesShow && nodesShow.length>0){
					//process the ancient nodes if _keywords is not blank
					if(_keywords.length>0){ 
						$.each(nodesShow, function(n,obj){
							var pathOfOne = obj.getPath();//get all the ancient nodes including current node
							if(pathOfOne && pathOfOne.length>0){ 
								//i < pathOfOne.length-1 process every node in path except self
								for(var i=0;i<pathOfOne.length-1;i++){
									zTreeObj.showNode(pathOfOne[i]); //show node 
									zTreeObj.expandNode(pathOfOne[i],true); //expand node
								}
							}
						});	
					}else{ //show all nodes when _keywords is blank and expand the root nodes
						var rootNodes = zTreeObj.getNodesByParam('level','0');//get all root nodes
						$.each(rootNodes,function(n,obj){
							zTreeObj.expandNode(obj,true); //expand all root nodes
						});
					}
				}
			}
			
			//listen to change in input element
			$(searchField).bind('input propertychange', function() {
				var _keywords = $(this).val();
				searchNodeLazy(_keywords); //call lazy load
			});

			var timeoutId = null;
			var lastKeyword = '';
			// excute lazy load once after input change, the last pending task will be cancled  
			function searchNodeLazy(_keywords) {
				if (timeoutId) { 
					//clear pending task
					clearTimeout(timeoutId);
				}
				timeoutId = setTimeout(function() {
			if (lastKeyword === _keywords) {
				return;
			}
					ztreeFilter(zTreeObj,_keywords); //lazy load ztreeFilter function 
					// $(searchField).focus();//focus input field again after filtering
			lastKeyword = _keywords;
				}, 500);
			}
		}
    },
}
</script>

<style lang='scss' scoped>
    @import '../plugins/zTree/css/zTreeStyle/zTreeStyle.css';
	.ztree {
		padding: 0;
		max-height: 28rem;
		overflow: auto;
		&::-webkit-scrollbar-track-piece { //滾動條凹槽的顏色,還可以設置邊框屬性
			background-color:#f8f8f8;
		}

		&::-webkit-scrollbar {//滾動條的寬度
			width:6px;
			height:6px;
		}

		&::-webkit-scrollbar-thumb {//滾動條的設置
			background-color:#dddddd;
			background-clip:padding-box;
			min-height:28px;
		}

		&::-webkit-scrollbar-thumb:hover {
			background-color:#bbb;
		}
	}
	.tree-box {
		padding: 0 .8rem;
	}
	
    #areaTree{
		// min-height: 30rem;
		margin-bottom: 2px;
		padding-bottom: 1rem;
		.addnode {
			display: flex;
			justify-content: center;
			padding: .4rem 0;
			// border-bottom: 1px solid #d9e2eb;
		}
		.boxtitle{
			display: flex;
			justify-content: space-around;
			margin: .5rem .8rem;
			button {
				margin-left: 0.5rem;
			}
		}
    }
</style>

4.組件使用

<ztree :treedata='treedata' :addtype='addtype' v-on:addtreeNode="addtreeNode" v-on:zTreeBeforeRename="zTreeBeforeRename" v-on:zTreeOnClick="zTreeOnClick" v-on:addzTreeOne="addzTreeOne" v-on:shuaxin="shauxin" v-on:removeTreeNode="removeTreeNode"></ztree>

treedata:後臺返回的tree數據格式

"data":[
        {
            "catalogName":"文件夾1",    //節點名字
            "dataSourceGroupId":"111", //節點ID
            "parentDSource":"NULL",    //父級ID
            "type":"1"                 //自定義屬性: 1-文件夾 0-文件
        },
        {
            "catalogName":"文件2",      //節點名字
            "dataSourceGroupId":"rrr",  //節點ID
            "parentDSource":"222",      //父級ID
            "type":"0"                  //自定義屬性: 1-文件夾 0-文件
        },
    ],

addtype: 添加根節點的顯示隱藏

addtreeNode: 添加子節點的顯示隱藏

zTreeBeforeRename: 編輯節點回調函數

 // 編輯節點
        zTreeBeforeRename(obj) {
            this.nodeName=obj.treeNode.catalogName;
        },

zTreeOnClick:點擊單個節點回調

// 點擊單個節點
        zTreeOnClick(obj) {
			if(obj.treeNode.type==1){
                //點擊的是文件夾
            }
            if(obj.treeNode.type==0){
                //點擊的是文件
            }
        },

addzTreeOne:添加根目錄回調

// 添加根節點
        addzTreeOne() {
    
        },

shauxin:刷新樹結構

// 刷新樹結構
        shauxin() {
            //重新獲取tree數據
        },

removeTreeNode:刪除節點

//移除節點
removeTreeNode(obj) {
    
}

在添加和刪除之後如果直接調用後臺接口刷新樹結構會導致樹結構的展開、選中等操作初始化,可以使用下面代碼對樹結構進行跟新

添加節點:

//發送添加節點請求....
   if(res.status == 200) { 
        //請求成功後
        var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
        var parentZNode = treeObj.getSelectedNodes(); //獲取父節點
        var newNode = {
            catalogName: this.collectionName,//節點名字
            dataSourceGroupId: res.data.id,//節點id
            parentDSource: this.nodeid, //父級id,可以在點擊單個節點時存下
            type: 1,  //自定義屬性
            icon: icojq  //圖標
            iconOpen: files, //展開時圖標
            iconClose: file, //閉合時圖標
        };
        newNode.nodeFlg = 1; // 可以自定義節點標識
        newNode = treeObj.addNodes(parentZNode[0], newNode, true);
    }

編輯節點:

//發送修改節點請求...
if(res.status == 200) {
    //請求成功
     var zTree = $.fn.zTree.getZTreeObj("treeDemo");
     this.nodeobj.treeNode.catalogName = this.ruleForm.baseNodeName;
     zTree.updateNode(this.nodeobj.treeNode);
     this.conName = '';
 }

刪除節點:

//發送刪除請求...
if(res.status == 200) {
    //請求成功
    var treeObj = $.fn.zTree.getZTreeObj(obj.treeId);
    var parentZNode = treeObj.getNodesByParam("dataSourceGroupId", obj.treeNode.dataSourceGroupId, null);
    treeObj.removeNode(parentZNode[0]);
}

圖標根據項目圖片位置引入即可:

import icojq from "@/assets/img/23.png"
import file from "@/assets/img/21.png"
import files from "@/assets/img/22.png"

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章