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 Event学习第七章 事件属性
Feb 07 Javascript
jQuery 联动日历实现代码
May 31 Javascript
把input初始值不写value的具体实现方法
Jul 04 Javascript
jquery处理json对象
Nov 03 Javascript
javascript实现Table排序的方法
May 15 Javascript
如何利用Promises编写更优雅的JavaScript代码
May 17 Javascript
AngularJS包括详解及示例代码
Aug 17 Javascript
vue.js从安装到搭建过程详解
Mar 17 Javascript
JavaScript中闭包的详解
Apr 01 Javascript
jQuery实现标签子元素的添加和赋值方法
Feb 24 jQuery
JavaScript判断对象和数组的两种方法
May 31 Javascript
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
Apr 06 Vue.js
基于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/09/05 PHP
PHP array_multisort() 函数的深入解析
2013/06/20 PHP
php文件服务实现虚拟挂载其他目录示例
2014/04/17 PHP
php下pdo的mysql事务处理用法实例
2014/12/27 PHP
php与python实现的线程池多线程爬虫功能示例
2016/10/12 PHP
PHP7引入的&quot;??&quot;和&quot;?:&quot;的区别讲解
2019/04/08 PHP
js 获取浏览器高度和宽度值(多浏览器)
2009/09/02 Javascript
详解webpack和webpack-simple中如何引入css文件
2017/06/28 Javascript
基于jQuery Easyui实现登陆框界面
2017/07/10 jQuery
vue中实现移动端的scroll滚动方法
2018/03/03 Javascript
JS实现的缓冲运动效果示例
2018/04/30 Javascript
node.js监听文件变化的实现方法
2019/04/17 Javascript
使用vue-cli3新建一个项目并写好基本配置(推荐)
2019/04/24 Javascript
javascript设计模式 ? 外观模式原理与用法实例分析
2020/04/15 Javascript
Vue Cli3 打包配置并自动忽略console.log语句的方法
2020/04/23 Javascript
ant design vue 表格table 默认勾选几项的操作
2020/10/31 Javascript
[01:54]胎教DOTA2 准妈妈玩家现身中国区预选赛
2016/06/26 DOTA
python将多个文本文件合并为一个文本的代码(便于搜索)
2011/03/13 Python
python下实现二叉堆以及堆排序的示例
2017/09/29 Python
Python中实现单例模式的n种方式和原理
2018/11/14 Python
django做form表单的数据验证过程详解
2019/07/26 Python
基于Python实现船舶的MMSI的获取(推荐)
2019/10/21 Python
Python 如何展开嵌套的序列
2020/08/01 Python
如何基于python实现年会抽奖工具
2020/10/20 Python
python的scipy.stats模块中正态分布常用函数总结
2021/02/19 Python
Canvas制作旋转的太极的示例
2018/03/09 HTML / CSS
澳大利亚领先的宠物用品商店:VetSupply
2017/09/08 全球购物
来自世界各地的优质葡萄酒:VineShop24
2018/07/09 全球购物
北京天润融通.net面试题笔试题
2012/02/20 面试题
大学生个人简历自我评价
2013/11/16 职场文书
演讲稿开场白
2014/01/13 职场文书
高中运动会前导词
2015/07/20 职场文书
Python数据分析之绘图和可视化详解
2021/06/02 Python
Django REST framework 限流功能的使用
2021/06/24 Python
基于Pygame实现简单的贪吃蛇游戏
2021/12/06 Python
一文搞清楚MySQL count(*)、count(1)、count(col)区别
2022/03/03 MySQL