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 相关文章推荐
JQuery扩展插件Validate 2通过参数设置验证规则
Sep 05 Javascript
jQuery实现的一个自定义Placeholder属性插件
Aug 11 Javascript
javascript解三阶幻方(九宫格)
Apr 22 Javascript
JS+CSS实现自动切换的网页滑动门菜单效果代码
Sep 14 Javascript
Bootstrap Chart组件使用教程
Apr 28 Javascript
在Mac OS上安装使用Node.js的项目自动化构建工具Gulp
Jun 18 Javascript
AngularJS 与Bootstrap实现表格分页实例代码
Oct 14 Javascript
Bootstrap进度条实现代码解析
Mar 07 Javascript
Vue页面骨架屏注入方法
May 13 Javascript
浅谈React之状态(State)
Sep 19 Javascript
详解Vue2 添加对scss的支持
Jan 02 Javascript
JavaScript中layim之整合右键菜单的示例代码
Feb 06 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
在PHP中使用模板的方法
2008/05/24 PHP
php中用数组的方法设置cookies
2011/04/21 PHP
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
iis下php mail函数的sendmail配置方法(官方推荐)
2012/04/25 PHP
PHP邮件发送类PHPMailer用法实例详解
2014/09/22 PHP
php模拟服务器实现autoindex效果的方法
2015/03/10 PHP
JScript中的&quot;this&quot;关键字使用方式补充材料
2007/03/08 Javascript
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
基于jquery的关于动态创建DOM元素的问题
2010/12/24 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
JavaScript代码实现图片循环滚动效果
2020/03/19 Javascript
详解Vue单元测试Karma+Mocha学习笔记
2018/01/31 Javascript
在vue里面设置全局变量或数据的方法
2018/03/09 Javascript
nuxt.js 缓存实践
2018/06/25 Javascript
浅析JS中什么是自定义react数据验证组件
2018/10/19 Javascript
详解Bootstrap 学习(一)入门
2019/04/12 Javascript
jquery简易手风琴插件的封装
2020/10/13 jQuery
[49:21]2018DOTA2亚洲邀请赛3月30日 小组赛B组 Effect VS iG
2018/03/31 DOTA
压缩包密码破解示例分享(类似典破解)
2014/01/17 Python
Python字符串详细介绍
2015/05/09 Python
Linux 发邮件磁盘空间监控(python)
2016/04/23 Python
windows下安装python的C扩展编译环境(解决Unable to find vcvarsall.bat)
2018/02/21 Python
Python八大常见排序算法定义、实现及时间消耗效率分析
2018/04/27 Python
django富文本编辑器的实现示例
2019/04/10 Python
Python 获取ftp服务器文件时间的方法
2019/07/02 Python
python-Web-flask-视图内容和模板知识点西宁街
2019/08/23 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
使用Django的JsonResponse返回数据的实现
2021/01/15 Python
一个基于canvas的移动端图片编辑器的实现
2020/10/28 HTML / CSS
英国最受欢迎的在线隐形眼镜商店:VisionDirect.co.uk
2018/12/06 全球购物
电钳专业个人求职信
2014/01/04 职场文书
四议两公开实施方案
2014/03/28 职场文书
加油口号大全
2014/06/13 职场文书
领导班子四风查摆对照检查材料思想汇报
2014/10/05 职场文书
勤俭节约主题班会
2015/08/13 职场文书
趣味运动会口号
2015/12/24 职场文书