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 checkbox复选框全选功能简单实例
Oct 09 Javascript
node.js中RPC(远程过程调用)的实现原理介绍
Dec 05 Javascript
超详细的javascript数组方法汇总
Nov 21 Javascript
写给小白的JavaScript引擎指南
Dec 04 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
Sep 21 Javascript
js 打开新页面在屏幕中间的实现方法
Nov 02 Javascript
JavaScript 事件对内存和性能的影响
Jan 22 Javascript
单击按钮发送验证码,出现倒计时的简单实例
Mar 17 Javascript
为JQuery EasyUI 表单组件增加焦点切换功能的方法
Apr 13 jQuery
微信小程序引用公共js里的方法的实例详解
Aug 17 Javascript
基于Vue 实现一个中规中矩loading组件
Apr 03 Javascript
vue.js实现图书管理功能
Sep 24 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实现生成透明背景的PNG缩略图函数分享
2014/07/08 PHP
ThinkPHP中Session用法详解
2014/11/29 PHP
php运行提示:Fatal error Allowed memory size内存不足的解决方法
2014/12/17 PHP
PHP 中提示undefined index如何解决(多种方法)
2016/03/16 PHP
PHP请求Socket接口测试实例
2016/08/12 PHP
php版微信公众账号第三方管理工具开发简明教程
2016/09/23 PHP
PHP读取文本文件并逐行输出该行使用最多的字符与对应次数的方法
2016/11/25 PHP
PHP用函数嵌入网站访问量计数器
2017/10/27 PHP
浅谈PHP实现大流量下抢购方案
2017/12/15 PHP
JS格式化数字金额用逗号隔开保留两位小数
2013/10/18 Javascript
javascript验证只能输入数字和一个小数点示例
2013/10/21 Javascript
JS和JQUERY获取页面大小,滚动条位置,元素位置(示例代码)
2013/12/14 Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
2014/06/17 Javascript
JavaScript中获取高度和宽度函数总结
2014/10/08 Javascript
jquery实现简单的自动播放幻灯片效果
2015/06/13 Javascript
JS中dom0级事件和dom2级事件的区别介绍
2016/05/05 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
vue 实现数字滚动增加效果的实例代码
2018/07/06 Javascript
仿ElementUI实现一个Form表单的实现代码
2019/04/23 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
webpack 动态批量加载文件的实现方法
2020/03/19 Javascript
手把手教你如何编译打包video.js
2020/12/09 Javascript
[02:41]辉夜杯现场一家三口 “我爸玩风行 我玩血魔”
2015/12/27 DOTA
Django MEDIA的配置及用法详解
2019/07/25 Python
python小白学习包管理器pip安装
2020/06/09 Python
什么是python类属性
2020/06/10 Python
pytorch下的unsqueeze和squeeze的用法说明
2021/02/06 Python
Python之多进程与多线程的使用
2021/02/23 Python
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
怎么可以提高数据库查询数据的速度
2014/06/28 面试题
JavaScript实现页面动态验证码的实现示例
2021/03/23 Javascript
小学清明节活动方案
2014/03/08 职场文书
产品售后服务承诺书
2014/05/21 职场文书
个人租房协议书样本
2014/10/01 职场文书
个人借条范本
2015/05/25 职场文书
php实例化对象的实例方法
2021/11/17 PHP