Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现


Posted in Javascript onApril 01, 2019

写在前面

首先,本篇文章所开发的组件并非一个已经开源的上线组件,所以如果你急于需要一个插件来只做你的项目,那么并不能带给你及时的帮助。这个组件的开发预计写两篇文章,一遍写组件,一篇写组件逻辑。这篇文章也是我自己开发的从无到有的过程,所以它可以为你提供一些Tree组件开发的思路,代码写到一定程度,不能完全依赖插件了,有时间可以看看插件源码或者动手去开发,这样真的能加深对技术的掌握程度。

开发过程

1.数据仓库-Vuex

2.组件的循环创建-递归组件

需求决定了我的技术选型,项目需求是一个中国各级政府列表的选择,后台基于大数据去汇总各级政府网站的文章决策,然后交给前端去展示,左侧显示各级政府的Tree,右侧显示具体文章。因为政府数据的不确定性,所以显示政府的Tree的每一层级也是动态获取的,就比如北京市下级的海淀区政府在一小时前可能不存在某某政策文章,那么北京市节点的子节点中就不会包含海淀区这一子节点,但是10分钟前网站发布了一篇文章,那么就需要在北京市中添加海淀区,为了良好的实时性效果,每一级的子节点都不固定。

因此 树状结构的data是变化的而不是在初始化的时候就固定好 的,数据驱动Dom的思想,data有多少层级,Dom就有多少层级,data不定,所以Dom也无法提前定义好层级,决定采用Vue的递归组件,组件递归自身实现无限制层级的渲染。需求中每一个节点的Tree都具有增删改的功能,因为data是单例的,全局维护着一个data数据源头,增删改也就是操作data第n个子节点的某个子元素,因此采用了Vuex作为一个data存放的仓库( 这不是一个组件库,只是一个项目的应用 )。

项目的关键点:

1.动态加载子节点,也就是说页面加载的时候,根节点的 nodes 子节点数组可能是个空数组,每次单击节点去获取子节点数组。

2.全局单例的树节点对象 data 对象,每次得到新的子节点,需要去维护这个对象,因为数据与dom动态绑定,所以每次数据对象内部发生了变化,dom也会重绘。

vue对虚拟dom的映射通过使用diff算法进行了优化,所以不用担心,重绘造成页面闪屏

树 data 数据结构如下:

let data = {
 id: "01",
 lable: "政府机构",
 nodes: [
  {
  id: "02",
  lable: "中央机关",
  nodes: [{
   //..
  }]
  },
  {
  id: "03",
  lable: "直辖市",
  nodes: [{
   //..
   //北京市...
   //天津市..
  }]
  },
 ]
 };

显示成这样:

Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现

每一个节点包含id,label,nodes三个属性,nodes往下延伸子节点,一共有多少级不确定根据后台获取得到。

递归组件

一个简单的递归组件的示例如下:

<template>
 <div class="tree-menu">
 //组件内部不断用自身,只要子节点存在就递归调用
 <tree-menu v-for='(item, index) of dataNodes' :key='index'></tree-menu>
 </div>
</template>

<script>
export default {
 name:'TreeMenu',//组件名称必须写
 data() {
 return {
  dataNodes: {
  //...
  }
 }
 }
}
</script>

TreeMenu.vue声明组件TreeMenu,并向外暴露,在组件内部调用自身,也就是一个递归的思想,绑定的dataNodes有多少层级,那就会递归多少层,因为每一层都有v-for都会循环子节点。绑定具体数据的时候再具体分析。不断调用自身,当然这只是一个例子,实际情况还要改造一下:

新建TreeMenu.vue,作为显示节点的逻辑组件:

<template>
 <div class="tree-menu">
 <div>{{label}}</div>//节点名称
 <tree-menu //如果nodes.length>0就递归显示子节点
  v-for="(node, index) of nodes" 
  :key="index" 
  :nodes="node.nodes" //子节点的子节点向下传递
  :label="node.label"
 >
 </tree-menu>
 </div>
</template>

<script>
export default {
 name: "TreeMenu",
 props:['label','nodes'],//数据通过pros向下传递,全局唯一数据源
 data() {
 return {}; 
 }
};
</script>

创建Tree.vue作为节点树的入口:

<template>
 <div class="tree-alone">
 <tree-menu :label="tree.label" :nodes="tree.nodes"></tree-menu>
 </div>
</template>
<script>
 import TreeMenu from './TreeMenu.vue'
 export default {
 name: 'tree',
 data() {
  return {
   tree: {
   id: "01",
   lable: "总层级",
   nodes: [
    {
    id: "02",
    label: "层级1",
    nodes: [{
     label: '层级1-1'
    }]
    },
    {
    id: "03",
    label: "层级2",
    nodes: []
    },
   ]
   };
 }
  }
 },
 components: {
  TreeMenu
 }
 }
</script>

在Tree.vue入口组件里引入子组件TreeMenu.vue,并且向子组件传递数据label和nodes,这里data先预定义一个简单的对象,后面会动态获取。

TreeMenu.vue作为树形菜单组件,负责递归和数据渲染,它会接受来自入口组件传递来的label和nodes数据,进行渲染, 并且继续递归传递nodes和label 。

在从父组件接收nodes和label后,先循环渲染n个tree-menu组件,然后每一个tree-menu又会递归自身,所以数据就这样一层层向下传递nodes=>nodes.node=>nodes.node.node,此时已经完成了数据与Dom的绑定,可以修改一下Tree.vue中的tree数据源,看一下组件是否动态改变了。现在渲染如下图:

Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现

数据正确渲染,现在需要加一些样式和点击事件(展开与收缩),就不做详细介绍了,代码如下: (向下传递depth参数来获取层级索引)

//Tree.vue
<template>
 <div class="tree-alone">
 <tree-menu :label="tree.label" :nodes="tree.nodes" :depth="0"></tree-menu>
 </div>
</template>

//TreeMenu.vue
<template>
 <div class="tree-menu">
 <div :style="indent" @click="toggleChildren">{{label}}</div>
 <div v-if="showChildren">
  <tree-menu
  v-for="(item, index) of nodes"
  :key="index"
  :nodes="node.nodes"
  :label="node.label"
  :depth="depth + 1"
  ></tree-menu>
 </div>
 </div>
</template>

<script>
export default {
 name: "TreeMenu",
 props: ["label", "nodes"],
 data() {
 return {
  showChildren: false
 };
 },
 methods: {
 toggleChildren() {
  this.showChildren = !this.showChildren;
 }
 },
 computed: {
 indent() {
  return { transform: `translate(${this.depth * 20}px)` };
 }
 }
};
</script>

修改后会展开收缩与缩进,一些箭头旋转等样式问题就不详细写了。

Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现

总结

以上所述是小编给大家介绍的Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript(jquery)利用函数修改全局变量的代码
Nov 02 Javascript
jquery validate.js表单验证的基本用法入门
May 13 Javascript
Mootools 图片展示插件(lightbox,ImageMenu)收集集合
May 21 Javascript
jQuery实现长文字部分显示代码
May 13 Javascript
Jquery创建层显示标题和内容且随鼠标移动而移动
Jan 26 Javascript
node.js入门教程
Jun 01 Javascript
全面了解js中的script标签
Jul 04 Javascript
jQuery事件用法详解
Oct 06 Javascript
Angularjs 动态改变title标题(兼容ios)
Dec 29 Javascript
关于不同页面之间实现参数传递的几种方式讨论
Feb 13 Javascript
JQuery查找子元素find()和遍历集合each的方法总结
Mar 07 Javascript
JavaScript表单即时验证 验证不成功不能提交
Aug 31 Javascript
基于vue框架手写一个notify插件实现通知功能的方法
Mar 31 #Javascript
基于elementUI实现图片预览组件的示例代码
Mar 31 #Javascript
微信小程序访问豆瓣电影api的实现方法
Mar 31 #Javascript
vue项目首屏打开速度慢的解决方法
Mar 31 #Javascript
jQuery事件blur()方法的使用实例讲解
Mar 30 #jQuery
Javascript实现一朵从含苞到绽放的玫瑰
Mar 30 #Javascript
使用post方法实现json往返传输数据的方法
Mar 30 #Javascript
You might like
phpMyAdmin2.11.6安装配置方法
2008/08/24 PHP
PHP中的Memcache详解
2014/04/05 PHP
Codeigniter上传图片出现“You did not select a file to upload”错误解决办法
2014/06/12 PHP
PHP实现绘制3D扇形统计图及图片缩放实例
2014/10/01 PHP
PHP多态代码实例
2015/06/26 PHP
PHP实现的进度条效果详解
2016/05/03 PHP
jQuery客户端分页实例代码
2013/11/18 Javascript
javascript简单实现表格行间隔显示颜色并高亮显示
2013/11/29 Javascript
轻松创建nodejs服务器(7):阻塞操作的实现
2014/12/18 NodeJs
Javascript 完美运动框架(逐行分析代码,让你轻松了运动的原理)
2015/01/23 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
jQuery简单实现title提示效果示例
2016/08/01 Javascript
js实现复制功能(多种方法集合)
2018/01/06 Javascript
Nodejs模块载入运行原理
2018/02/23 NodeJs
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
2019/02/19 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
2019/09/01 Javascript
[01:10:02]IG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
通过实例浅析Python对比C语言的编程思想差异
2015/08/30 Python
使用Kivy将python程序打包为apk文件
2017/07/29 Python
详解Python的hasattr() getattr() setattr() 函数使用方法
2018/07/09 Python
Pyqt5如何让QMessageBox按钮显示中文示例代码
2019/04/11 Python
Django--权限Permissions的例子
2019/08/28 Python
Django中提示消息messages的设置方式
2019/11/15 Python
Python3 mmap内存映射文件示例解析
2020/03/23 Python
keras 获取某层的输入/输出 tensor 尺寸操作
2020/06/10 Python
对python中list的五种查找方法说明
2020/07/13 Python
html5如何在Canvas中实现自定义路径动画示例
2017/09/18 HTML / CSS
英国奢侈品网站:MatchesFashion
2016/12/16 全球购物
2014年庆元旦活动方案
2014/02/15 职场文书
医院反腐倡廉演讲稿
2014/09/16 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
业务员管理制度范本
2015/08/06 职场文书
工作后的感想
2015/08/07 职场文书
家长对孩子的寒假评语
2015/10/09 职场文书
python中24小时制转换为12小时制的方法
2021/06/18 Python
python随机打印成绩排名表
2021/06/23 Python