当前位置:   article > 正文

Vue编写的树形tree组件_vue tree

vue tree

近期在进行vue的学习,自研的vue项目需要一个tree组件。由于在学习阶段,不想‘拿来主义’,拿别人写好的组件使用,对于处于学习阶段的开发者来说不是一件好事,虽然拿别人开发好的东西过来用可以快速进行业务开发,但阻绝了学习者锻炼自身开发技能的机会。‘拿来主义’的学习方式,与其说是学习一门语言,不如说是学习一种成熟组件的使用方式。自己动手写一写还是非常有利于自身水平提升的。于是,开始动手自己写vue-tree组件。

代码:

  1. <template>
  2. <div class='cus_vtree_wrap' @click.capture='clickNodeWrap'>
  3. <v-tree-item :treeData='treeData' @clickNodeCom='clickNode' :checkBox='checkBox' :class='{tree_root_lonely:treeData.length === 1}' @toggleCheckBox="checkBoxFun"></v-tree-item>
  4. </div>
  5. </template>
  6. <script>
  7. export default{
  8. name:'vue-tree',
  9. props:['treeData','checkBox'],
  10. data(){
  11. return {
  12. //userData:this.treeData
  13. }
  14. },
  15. mounted(){
  16. this.initData(true,true,true);
  17. },
  18. updated(){
  19. this.initData(true,true,true);
  20. },
  21. methods:{
  22. initData(expandInit,activeInit,checkedInit){
  23. var self = this;
  24. var modifyDataFun = function(datas){
  25. if(datas){
  26. datas.forEach( (m,index) => {
  27. if(expandInit){
  28. self.$set(m,'expand',true);
  29. }
  30. if(activeInit){
  31. self.$set(m,'active',false);
  32. }
  33. if(checkedInit){
  34. self.$set(m,'checked',false);
  35. self.$set(m,'partchecked',false);
  36. }
  37. if(index === datas.length - 1){
  38. self.$set(m,'last',true);
  39. }
  40. if(m.children){
  41. modifyDataFun(m.children);
  42. }
  43. });
  44. }
  45. }
  46. modifyDataFun(this.treeData);
  47. },
  48. clickNode(data){
  49. this.$emit('clickNode',data);
  50. },
  51. clickNodeWrap(){
  52. this.initData(false,true,false);
  53. },
  54. checkBoxFun(item){
  55. },
  56. getCheckedNodes(){
  57. var resultArr = [];
  58. var getCheckedNodesFun = (datas) => {
  59. if(datas){
  60. datas.forEach((m)=>{
  61. if(m.checked === true){
  62. resultArr.push(m);
  63. }
  64. if(m.children){
  65. getCheckedNodesFun(m.children);
  66. }
  67. })
  68. }
  69. };
  70. getCheckedNodesFun(this.treeData);
  71. return resultArr;
  72. },
  73. getRoot(){
  74. return this.treeData[0];
  75. },
  76. findNode(selectedId){
  77. var result;
  78. var findNodeFun = (datas) => {
  79. if(datas){
  80. try{
  81. datas.forEach((m) => {
  82. if(m.id === selectedId){
  83. result = m;
  84. throw new Error('stop');
  85. }
  86. if(m.children){
  87. findNodeFun(m.children);
  88. }
  89. });
  90. }catch(e){
  91. }
  92. }
  93. };
  94. findNodeFun(this.treeData);
  95. return result;
  96. },
  97. setSelectedNode(node,clickDiv){
  98. var select;
  99. var that = this;
  100. var setSelectedFun = (datas) => {
  101. if(datas){
  102. datas.forEach((m) => {
  103. if(m.id === node.id){
  104. m.active = true;
  105. select = m;
  106. if(clickDiv) {
  107. var dom = document.getElementById(m.id);
  108. if(dom && dom.className.indexOf('cus_item_content') > -1){
  109. dom.click();
  110. }else {
  111. var doms = document.getElementsByClassName('cus_item_content');
  112. for(var y = 0 ; y < doms.length ;y ++){
  113. if(doms[y].id === m.id){
  114. doms[y].click();
  115. break;
  116. }
  117. }
  118. }
  119. }
  120. }else {
  121. m.active = false;
  122. }
  123. if(m.children){
  124. setSelectedFun(m.children);
  125. }
  126. });
  127. }
  128. };
  129. setSelectedFun(this.treeData);
  130. return select;
  131. },
  132. getSelectedNode(){
  133. var resultNode = null;
  134. var getSelectedFun = (datas) => {
  135. if(datas){
  136. datas.forEach((m) => {
  137. if(m.active === true){
  138. resultNode = m;
  139. return;
  140. }
  141. if(m.children){
  142. getSelectedFun(m.children)
  143. }
  144. })
  145. }
  146. };
  147. getSelectedFun(this.treeData);
  148. return resultNode;
  149. },
  150. getParentNode(node){
  151. var resultNode = null;
  152. var getParentNode = (datas,parent) => {
  153. if(datas){
  154. try{
  155. datas.forEach( (m) => {
  156. if(node && m.id === node.id){
  157. resultNode = parent;
  158. throw new Error("Stop");
  159. }
  160. if(!resultNode && m.children){
  161. getParentNode(m.children,m);
  162. }
  163. } );
  164. }catch(e){
  165. }
  166. }
  167. }
  168. getParentNode(this.treeData,null);
  169. return resultNode;
  170. },
  171. getParentNodesArr(node){
  172. var resultArr = [];
  173. var parentNode ;
  174. var getParent = (target) => {
  175. parentNode = this.getParentNode(target);
  176. if(parentNode){
  177. resultArr.push(parentNode);
  178. getParent(parentNode);
  179. }
  180. };
  181. getParent(node);
  182. return resultArr;
  183. }
  184. },
  185. components:{'v-tree-item':{
  186. name:'v-tree-item',
  187. 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}">'+
  188. '<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>'+
  189. '<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>'+
  190. '<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>',
  191. methods:{
  192. clickNode(item){
  193. item.active = true;
  194. this.$emit('clickNodeCom',item);
  195. },
  196. toggleNode(item){
  197. item.expand = !item.expand;
  198. item.active = true;
  199. },
  200. clickNodeCom(data){
  201. this.$emit('clickNodeCom',data);
  202. },
  203. checkBoxClick(item){
  204. item.partchecked = false;
  205. item.checked = !item.checked;
  206. //设置子元素是否勾选
  207. var checkChildFun = (childrenDatas) => {
  208. childrenDatas.forEach((m) => {
  209. m.checked = item.checked;
  210. if(m.children){
  211. checkChildFun(m.children);
  212. }
  213. })
  214. }
  215. if(item.children){
  216. checkChildFun(item.children);
  217. }
  218. this.$emit('toggleCheckBox');
  219. },
  220. checkBoxFun(item){
  221. var checkedNum = 0;
  222. var partCheckedNum = 0;
  223. item.children.forEach((li) => {
  224. if(li.checked === true){
  225. checkedNum++;
  226. }else if(li.partchecked === true){
  227. partCheckedNum++;
  228. }
  229. })
  230. if(checkedNum === item.children.length){ //全选
  231. item.checked = true;
  232. item.partchecked = false;
  233. }else if(checkedNum > 0 || partCheckedNum > 0){ //部分勾选
  234. item.checked = false;
  235. item.partchecked = true;
  236. }else{ //没有勾选
  237. item.checked = false;
  238. item.partchecked = false;
  239. }
  240. this.$emit('toggleCheckBox')
  241. },
  242. },
  243. props:['treeData','checkBox']
  244. }}
  245. }
  246. </script>
  247. <style>
  248. .cus_vtree_wrap>ul:first-child{
  249. background-image:none;
  250. }
  251. ul.cus_tree_ul{
  252. padding-left:16px;
  253. background-image:url('../images/index.gif');
  254. background-position:4px 10px;
  255. background-repeat:repeat-y;
  256. }
  257. li:last-child>ul.cus_tree_ul:last-child{
  258. background-image:none;
  259. }
  260. ul.cus_tree_ul li{
  261. text-align:left;
  262. cursor:pointer;
  263. list-style:none;
  264. }
  265. .cus_item_content span.treeExpandBtn{
  266. display:inline-block;
  267. width:18px;
  268. height:18px;
  269. margin-right:6px;
  270. background-image:url('../images/zTreeStandard.png');
  271. }
  272. .cus_vtree_wrap>ul> li:first-child>.cus_item_content>span.treeExpandBtn.butopen{
  273. background-position:-92px 0px
  274. }
  275. li .cus_item_content span.treeExpandBtn.butopen{
  276. background-position:-92px -18px
  277. }
  278. li:last-child .cus_item_content span.treeExpandBtn.butopen{
  279. background-position:-92px -36px
  280. }
  281. .cus_vtree_wrap ul.tree_root_lonely>li>.cus_item_content>span.treeExpandBtn.butopen{
  282. background-position:-92px -54px
  283. }
  284. .cus_vtree_wrap>ul> li:first-child>.cus_item_content>span.treeExpandBtn.btnclose{
  285. background-position:-74px -0px
  286. }
  287. li .cus_item_content span.treeExpandBtn.btnclose{
  288. background-position:-74px -18px
  289. }
  290. li:last-child .cus_item_content span.treeExpandBtn.btnclose{
  291. background-position:-74px -36px
  292. }
  293. .cus_vtree_wrap ul.tree_root_lonely>li>.cus_item_content>span.treeExpandBtn.btnclose{
  294. background-position:-74px -54px
  295. }
  296. .cus_item_content span.treeExpandBtn.lastLine{
  297. background-position:-56px -36px
  298. }
  299. .cus_item_content span.treeExpandBtn.line{
  300. background-position:-56px -18px
  301. }
  302. .cus_item_content .cus_chekcbox{
  303. display:inline-block;
  304. width:14px;
  305. height:14px;
  306. margin-right:6px;
  307. background-image:url('../images/zTreeStandard.png');
  308. background-position:-0px -0px
  309. }
  310. .cus_item_content .cus_chekcbox.cus_chekcbox_checked{
  311. background-position:-14px -0px
  312. }
  313. .cus_item_content .cus_chekcbox.cus_chekcbox_part_checked{
  314. background-position:0px -42px
  315. }
  316. ul.cus_tree_ul li .cus_item_content{
  317. padding:4px;
  318. white-space: nowrap;
  319. overflow-x:hidden;
  320. }
  321. ul.cus_tree_ul li .cus_item_content:hover{
  322. background:#8f83e1;
  323. color:white
  324. }
  325. ul.cus_tree_ul li .cus_item_content.active{
  326. background:#7663f8;
  327. color:white;
  328. }
  329. .folder{
  330. display:inline-block;
  331. width:16px;
  332. height:16px;
  333. margin-right:6px;
  334. background-image:url('../images/zTreeStandard.png');
  335. background-position:-110px -0px
  336. }
  337. .file{
  338. display:inline-block;
  339. width:18px;
  340. height:18px;
  341. margin-right:6px;
  342. background-image:url('../images/zTreeStandard.png');
  343. background-position:-110px -30px
  344. }
  345. </style>

效果图:

使用方式:

            安装:npm install vue-tree-jf --save

             引用:

  1. import vueTree from 'vue-tree-jf'
  2. Vue.use(vueTree);
  3. .....
  4. <vue-tree :treeData='datas' ref='vtree' @clickNode ='clickNode' ></vue-tree>

初始化参数

参数类型默认值描述
treeDataArray数据源,包含'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', }] } ]
checkBoxBoolenfalse是否显示checkbox
transitionTimeNumber200折叠动画时间,单位ms
expandBooleantrue初始化时是否展开节点

treeData参数

参数名称类型默认值描述
textString节点名称
idString节点id
iconString节点图标
childrenArray节点的子节点

方法

方法名称参数返回值描述
getSelectedNode-返回选中的tree节点
getCheckedNodes-返回多选的tree节点在多选属性checkbox为true时有效。
getRoot-获取树根节点。
findNodenodeId节点id获根据id获取选中节点数据。
setSelectedNodenode,ifClicknode:节点数据,包含id字段即可。 ifClick:是否触发点击事件设置树节点选中。
getParentNodenodenode:节点对象(包含id属性即可)获取父节点数据。
getParentNodesArrnodenode:节点对象(包含id属性即可)获取所有祖先节点数据数组。

事件说明

事件名称参数参数说明描述
clickNodenode当前点击节点的数据节点点击时触发

文件更新(2020/12/2)

更新版本(1.0.7):

1.修改选中样式;

2.新增折叠动画特效,通过transitionTime控制折叠动画时间

完整项目github:GitHub - jianfeng418/vue-tree: vue vue-tree vue-checkbox-tree

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/119269?site
推荐阅读