近期在进行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组件相关推荐

  1. ant vue 树形菜单横向显示_丝滑般 Vue 拖拽排序树形表格组件Vue-DragTreeTable

    今天给小伙伴们分享一款纵享丝滑般体验的Vue拖拽树形表格DragTreeTable. vue-drag-tree-table 基于vue.js实现可拖拽排序的树形表格组件.支持拖拽排序.固定表头.拖拽 ...

  2. 基于 vue 编写的vue图片预览组件,支持单图和多图预览,仅传入一个图片地址,即可实现图片预览效果,可自定义背景、按钮颜色等

    hevue-img-preview 简介 完整版下载地址:基于 vue 编写的vue图片预览组件 本组件是一个基于 vue 编写的 vue 图片预览组件,支持 pc 和手机端,支持单图和多图预览,仅传 ...

  3. Vue封装树形菜单组件

    csdn终于更新完成了哈,ok,步入正题 像这种树形结构的核心思想就是:递归思想,知道使用递归,其实这个例子函数的封装也就很简单喽 实现步骤: 设置的props:                    ...

  4. vue中element ui 中tree组件怎么自定义前缀图标呢?

    一 问题 饿了么ui 默认的图标样式是: 1. 一个箭头, 展开自动顺时针旋转90°, 以上的条件是该节点有子节点, 2. 如果是没有子节点的节点, 是默认空白图标的(这里我认为他不是没有, 而是有占 ...

  5. 移动端vue实现部门结构功能_基于Vue的组织架构树组件

    由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vue).在GitHub上找了半天,这类组件不多,也没有符合业务需求的组件,所以决定自己造轮子! 分析 既然是树,那么每个节点都应该 ...

  6. bootstrap树节点如何设置默认不展开_我开源了一个基于Vue的组织架构树组件

    开门见山 Demo 演示地址:http://www.longstudy.club/vue... github 地址:https://github.com/qq44924588... 项目背景 因为最近 ...

  7. 移动端vue实现部门结构功能_基于Vue制作组织架构树组件

    编程之家收集整理的这篇文章主要介绍了基于Vue制作组织架构树组件,编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考. 由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vu ...

  8. iview自定义Tree组件内容

    介绍 Vue完整前后台项目介绍 使用iview框架进行开发的话,一般都有展示树形结构数据的需求.那么就用的到其中的Tree组件了.但是其基本架构是满足不了我们的需求的,基本架构如下: 一般来说一条数据 ...

  9. Vue多个单文件组件使用

    在project目录下创建components文件夹,然后将所有子组件放入components文件夹下  [创建此目录][文件名的首字母大写] 1.多组件嵌套使用 Child1.vue <tem ...

最新文章

  1. 用Unity的视频广告创建2D动作游戏 Create Action 2D Game With Video Ads In Unity
  2. 服务器上找不到iis,解决IIS服务器部署 字体图标找不到的原因
  3. 厦大计算机研究生和福大,考研:只知道厦门大学?福建还有这些211值得你了解...
  4. SharePoint 2013 配置基于AD的Form认证
  5. python中的time库安装步骤-Python中time模块的使用
  6. 【BZOJ 3171】 [Tjoi2013]循环格
  7. Linux中的Interrupted system call错误
  8. raspberry pi_如何使用Raspberry Pi构建WiFi相框
  9. 我能想到的圆角背景的实现方法
  10. http客户端-性能比较系列-第二篇-多线程
  11. AMD显卡在WIN10环境下刷新BIOS
  12. Engineering Dynamics 2 --- 动量和角动量
  13. vue中的浏览量_vue项目中使用百度统计
  14. 使用pandas的merge出现Empty DataFrame 和 Index: []
  15. outlook2010保留服务器邮件,outlook 保留服务器邮件
  16. 大型Web网站优化总结一
  17. 深度学习-吴恩达第一课第二周课程作业
  18. 今日头条校招真题——头条校招
  19. redis入门到精通(一) - 编译与调试
  20. 基于SPI的OLED显示

热门文章

  1. 微信小程序打开PDF文件
  2. apidoc php,使用apidoc为你的项目编写api文档
  3. 【tk实现学生管理系统】
  4. 耳机坏了怎么办---------自己修呗
  5. 【单片机毕业设计】【mcuclub-jk-006】基于单片机的医院输液的设计
  6. 用了这个技术,我的元宵照片竟然艺术感爆表
  7. 一个被图灵奖遗忘的暴脾气老大爷:LSTM之父又发威!
  8. <数据结构>时间复杂度及空间复杂度
  9. jQuery weui 滚动加载
  10. 前端怎么把px单位换成rem单位解决项目页面适配问题