Vue编写的树形tree组件
近期在进行vue的学习,自研的vue项目需要一个tree组件。由于在学习阶段,不想‘拿来主义’,拿别人写好的组件使用,对于处于学习阶段的开发者来说不是一件好事,虽然拿别人开发好的东西过来用可以快速进行业务开发,但阻绝了学习者锻炼自身开发技能的机会。‘拿来主义’的学习方式,与其说是学习一门语言,不如说是学习一种成熟组件的使用方式。自己动手写一写还是非常有利于自身水平提升的。于是,开始动手自己写vue-tree组件。
代码:
<template><div class='cus_vtree_wrap' @click.capture='clickNodeWrap'><v-tree-item :treeData='treeData' @clickNodeCom='clickNode' :checkBox='checkBox' :class='{tree_root_lonely:treeData.length === 1}' @toggleCheckBox="checkBoxFun"></v-tree-item></div>
</template><script>export default{name:'vue-tree',props:['treeData','checkBox'],data(){return {//userData:this.treeData}},mounted(){this.initData(true,true,true);},updated(){this.initData(true,true,true);},methods:{initData(expandInit,activeInit,checkedInit){var self = this;var modifyDataFun = function(datas){if(datas){datas.forEach( (m,index) => {if(expandInit){self.$set(m,'expand',true);}if(activeInit){self.$set(m,'active',false);}if(checkedInit){self.$set(m,'checked',false);self.$set(m,'partchecked',false);}if(index === datas.length - 1){self.$set(m,'last',true);}if(m.children){modifyDataFun(m.children);}});}}modifyDataFun(this.treeData);},clickNode(data){this.$emit('clickNode',data);},clickNodeWrap(){this.initData(false,true,false);},checkBoxFun(item){},getCheckedNodes(){var resultArr = [];var getCheckedNodesFun = (datas) => {if(datas){datas.forEach((m)=>{if(m.checked === true){resultArr.push(m);}if(m.children){getCheckedNodesFun(m.children);}})}};getCheckedNodesFun(this.treeData);return resultArr;},getRoot(){return this.treeData[0];},findNode(selectedId){var result;var findNodeFun = (datas) => {if(datas){try{datas.forEach((m) => {if(m.id === selectedId){result = m;throw new Error('stop');}if(m.children){findNodeFun(m.children);}});}catch(e){}}};findNodeFun(this.treeData);return result;},setSelectedNode(node,clickDiv){var select;var that = this;var setSelectedFun = (datas) => {if(datas){datas.forEach((m) => {if(m.id === node.id){m.active = true;select = m;if(clickDiv) {var dom = document.getElementById(m.id);if(dom && dom.className.indexOf('cus_item_content') > -1){dom.click();}else {var doms = document.getElementsByClassName('cus_item_content');for(var y = 0 ; y < doms.length ;y ++){if(doms[y].id === m.id){doms[y].click();break;}}}}}else {m.active = false;}if(m.children){setSelectedFun(m.children);}});}};setSelectedFun(this.treeData);return select;},getSelectedNode(){var resultNode = null;var getSelectedFun = (datas) => {if(datas){datas.forEach((m) => {if(m.active === true){resultNode = m;return;}if(m.children){getSelectedFun(m.children)}})}};getSelectedFun(this.treeData);return resultNode;},getParentNode(node){var resultNode = null;var getParentNode = (datas,parent) => {if(datas){try{datas.forEach( (m) => {if(node && m.id === node.id){resultNode = parent;throw new Error("Stop");}if(!resultNode && m.children){getParentNode(m.children,m);}} );}catch(e){}}}getParentNode(this.treeData,null);return resultNode;},getParentNodesArr(node){var resultArr = [];var parentNode ;var getParent = (target) => {parentNode = this.getParentNode(target);if(parentNode){resultArr.push(parentNode);getParent(parentNode);}};getParent(node);return resultArr;}},components:{'v-tree-item':{name:'v-tree-item',template:'<ul class="cus_tree_ul" :class="{cus_tree_ulLine:(treeData && treeData.length)}"><li v-for="item in treeData"><div class="cus_item_content" :title="item.text" @click="clickNode(item)" :id= item.id :class="{active:item.active}">'+'<span class="treeExpandBtn" @click.stop="toggleNode(item)" :class="{butopen:item.expand && item.children,btnclose:!item.expand && item.children,line: !item.last && !item.children,lastLine:item.last&&!item.children}"></span><span class="tree-icon" :class="item.icon"></span>'+'<span v-if="checkBox" @click="checkBoxClick(item)" class="cus_chekcbox" :class="{cus_chekcbox_checked:item.checked,cus_chekcbox_part_checked:item.partchecked}"></span>{{item.text}}</div>'+'<v-tree-item :treeData="item.children" v-if="item.expand" @clickNodeCom="clickNodeCom" :checkBox="checkBox" :class="{cus_checkbox_allchecked:item.checked}" @toggleCheckBox="checkBoxFun(item)" ></v-tree-item> </li></ul>',methods:{clickNode(item){item.active = true;this.$emit('clickNodeCom',item);},toggleNode(item){item.expand = !item.expand;item.active = true;},clickNodeCom(data){this.$emit('clickNodeCom',data);},checkBoxClick(item){item.partchecked = false;item.checked = !item.checked;//设置子元素是否勾选var checkChildFun = (childrenDatas) => {childrenDatas.forEach((m) => {m.checked = item.checked;if(m.children){checkChildFun(m.children);}})}if(item.children){checkChildFun(item.children);}this.$emit('toggleCheckBox');},checkBoxFun(item){var checkedNum = 0;var partCheckedNum = 0;item.children.forEach((li) => {if(li.checked === true){checkedNum++;}else if(li.partchecked === true){partCheckedNum++;}})if(checkedNum === item.children.length){ //全选item.checked = true;item.partchecked = false;}else if(checkedNum > 0 || partCheckedNum > 0){ //部分勾选item.checked = false;item.partchecked = true;}else{ //没有勾选item.checked = false;item.partchecked = false;}this.$emit('toggleCheckBox')},},props:['treeData','checkBox']}}}
</script><style>.cus_vtree_wrap>ul:first-child{background-image:none;}ul.cus_tree_ul{padding-left:16px;background-image:url('../images/index.gif');background-position:4px 10px;background-repeat:repeat-y;}li:last-child>ul.cus_tree_ul:last-child{background-image:none;}ul.cus_tree_ul li{text-align:left;cursor:pointer;list-style:none;}.cus_item_content span.treeExpandBtn{display:inline-block;width:18px;height:18px;margin-right:6px;background-image:url('../images/zTreeStandard.png');}.cus_vtree_wrap>ul> li:first-child>.cus_item_content>span.treeExpandBtn.butopen{background-position:-92px 0px}li .cus_item_content span.treeExpandBtn.butopen{background-position:-92px -18px}li:last-child .cus_item_content span.treeExpandBtn.butopen{background-position:-92px -36px}.cus_vtree_wrap ul.tree_root_lonely>li>.cus_item_content>span.treeExpandBtn.butopen{background-position:-92px -54px}.cus_vtree_wrap>ul> li:first-child>.cus_item_content>span.treeExpandBtn.btnclose{background-position:-74px -0px}li .cus_item_content span.treeExpandBtn.btnclose{background-position:-74px -18px}li:last-child .cus_item_content span.treeExpandBtn.btnclose{background-position:-74px -36px}.cus_vtree_wrap ul.tree_root_lonely>li>.cus_item_content>span.treeExpandBtn.btnclose{background-position:-74px -54px}.cus_item_content span.treeExpandBtn.lastLine{background-position:-56px -36px}.cus_item_content span.treeExpandBtn.line{background-position:-56px -18px}.cus_item_content .cus_chekcbox{display:inline-block;width:14px;height:14px;margin-right:6px;background-image:url('../images/zTreeStandard.png');background-position:-0px -0px}.cus_item_content .cus_chekcbox.cus_chekcbox_checked{background-position:-14px -0px}.cus_item_content .cus_chekcbox.cus_chekcbox_part_checked{background-position:0px -42px}ul.cus_tree_ul li .cus_item_content{padding:4px;white-space: nowrap;overflow-x:hidden;}ul.cus_tree_ul li .cus_item_content:hover{background:#8f83e1;color:white}ul.cus_tree_ul li .cus_item_content.active{background:#7663f8;color:white;}.folder{display:inline-block;width:16px;height:16px;margin-right:6px;background-image:url('../images/zTreeStandard.png');background-position:-110px -0px}.file{display:inline-block;width:18px;height:18px;margin-right:6px;background-image:url('../images/zTreeStandard.png');background-position:-110px -30px}
</style>
效果图:
使用方式:
安装:npm install vue-tree-jf --save
引用:
import vueTree from 'vue-tree-jf'Vue.use(vueTree);.....
<vue-tree :treeData='datas' ref='vtree' @clickNode ='clickNode' ></vue-tree>
初始化参数
参数 | 类型 | 默认值 | 描述 |
treeData | Array |
数据源,包含'id','text','icon','children'属性。 示例:[ {text:'xiaoming', id:'1', icon:'folder', children:[ {text:'1-1', id:'1-1', icon:'folder', children:[ {text:'1-1-1', id:'1-1-1', icon:'file', },{text:'1-1-2', id:'1-1-2', icon:'file' }] },{ text:'1-2', id:'1-2', icon:'folder', }] } ] |
|
checkBox | Boolen | false | 是否显示checkbox |
transitionTime | Number | 200 | 折叠动画时间,单位ms |
expand | Boolean | true | 初始化时是否展开节点 |
treeData参数
参数名称 | 类型 | 默认值 | 描述 |
text | String | 节点名称 | |
id | String | 节点id | |
icon | String | 节点图标 | |
children | Array | 节点的子节点 |
方法
方法名称 | 参数 | 返回值 | 描述 |
getSelectedNode | - | 返回选中的tree节点 | |
getCheckedNodes | - | 返回多选的tree节点 | 在多选属性checkbox为true时有效。 |
getRoot | - | 获取树根节点。 | |
findNode | nodeId | 节点id | 获根据id获取选中节点数据。 |
setSelectedNode | node,ifClick | node:节点数据,包含id字段即可。 ifClick:是否触发点击事件 | 设置树节点选中。 |
getParentNode | node | node:节点对象(包含id属性即可) | 获取父节点数据。 |
getParentNodesArr | node | node:节点对象(包含id属性即可) | 获取所有祖先节点数据数组。 |
事件说明
事件名称 | 参数 | 参数说明 | 描述 |
clickNode | node | 当前点击节点的数据 | 节点点击时触发 |
文件更新(2020/12/2)
更新版本(1.0.7):
1.修改选中样式;
2.新增折叠动画特效,通过transitionTime控制折叠动画时间
完整项目github:GitHub - jianfeng418/vue-tree: vue vue-tree vue-checkbox-tree
Vue编写的树形tree组件相关推荐
- ant vue 树形菜单横向显示_丝滑般 Vue 拖拽排序树形表格组件Vue-DragTreeTable
今天给小伙伴们分享一款纵享丝滑般体验的Vue拖拽树形表格DragTreeTable. vue-drag-tree-table 基于vue.js实现可拖拽排序的树形表格组件.支持拖拽排序.固定表头.拖拽 ...
- 基于 vue 编写的vue图片预览组件,支持单图和多图预览,仅传入一个图片地址,即可实现图片预览效果,可自定义背景、按钮颜色等
hevue-img-preview 简介 完整版下载地址:基于 vue 编写的vue图片预览组件 本组件是一个基于 vue 编写的 vue 图片预览组件,支持 pc 和手机端,支持单图和多图预览,仅传 ...
- Vue封装树形菜单组件
csdn终于更新完成了哈,ok,步入正题 像这种树形结构的核心思想就是:递归思想,知道使用递归,其实这个例子函数的封装也就很简单喽 实现步骤: 设置的props: ...
- vue中element ui 中tree组件怎么自定义前缀图标呢?
一 问题 饿了么ui 默认的图标样式是: 1. 一个箭头, 展开自动顺时针旋转90°, 以上的条件是该节点有子节点, 2. 如果是没有子节点的节点, 是默认空白图标的(这里我认为他不是没有, 而是有占 ...
- 移动端vue实现部门结构功能_基于Vue的组织架构树组件
由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vue).在GitHub上找了半天,这类组件不多,也没有符合业务需求的组件,所以决定自己造轮子! 分析 既然是树,那么每个节点都应该 ...
- bootstrap树节点如何设置默认不展开_我开源了一个基于Vue的组织架构树组件
开门见山 Demo 演示地址:http://www.longstudy.club/vue... github 地址:https://github.com/qq44924588... 项目背景 因为最近 ...
- 移动端vue实现部门结构功能_基于Vue制作组织架构树组件
编程之家收集整理的这篇文章主要介绍了基于Vue制作组织架构树组件,编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考. 由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vu ...
- iview自定义Tree组件内容
介绍 Vue完整前后台项目介绍 使用iview框架进行开发的话,一般都有展示树形结构数据的需求.那么就用的到其中的Tree组件了.但是其基本架构是满足不了我们的需求的,基本架构如下: 一般来说一条数据 ...
- Vue多个单文件组件使用
在project目录下创建components文件夹,然后将所有子组件放入components文件夹下 [创建此目录][文件名的首字母大写] 1.多组件嵌套使用 Child1.vue <tem ...
最新文章
- 用Unity的视频广告创建2D动作游戏 Create Action 2D Game With Video Ads In Unity
- 服务器上找不到iis,解决IIS服务器部署 字体图标找不到的原因
- 厦大计算机研究生和福大,考研:只知道厦门大学?福建还有这些211值得你了解...
- SharePoint 2013 配置基于AD的Form认证
- python中的time库安装步骤-Python中time模块的使用
- 【BZOJ 3171】 [Tjoi2013]循环格
- Linux中的Interrupted system call错误
- raspberry pi_如何使用Raspberry Pi构建WiFi相框
- 我能想到的圆角背景的实现方法
- http客户端-性能比较系列-第二篇-多线程
- AMD显卡在WIN10环境下刷新BIOS
- Engineering Dynamics 2 --- 动量和角动量
- vue中的浏览量_vue项目中使用百度统计
- 使用pandas的merge出现Empty DataFrame 和 Index: []
- outlook2010保留服务器邮件,outlook 保留服务器邮件
- 大型Web网站优化总结一
- 深度学习-吴恩达第一课第二周课程作业
- 今日头条校招真题——头条校招
- redis入门到精通(一) - 编译与调试
- 基于SPI的OLED显示