vuejs使用递归组件实现树形目录的方法


Posted in Javascript onSeptember 30, 2017

上篇文章我提到了通讯录的开发,里面的目录使用了vue的递归组件实现的树形目录,这篇文章就来讲讲如何实现树形目录吧!

首先实现效果如下,觉得菜单还是比较nice的是吧:

vuejs使用递归组件实现树形目录的方法

这边数据调用的是数据库的数据的,需要数据库进行数据的构造,这里涉及到java的构造多叉树的知识,后续我会另外写一篇文章详细讲解,这里讲下前端。

数据可以先构造json使用,这里用到的格式大概如下,以childList来嵌套子菜单:

{
  id:YH, 
  name:银行, 
  pid:0, 
  childList:[{
    id:YH******, 
    name:国家开发银行, 
    pid:YH, 
    childList:[{
      id:YH*****3, 
      name:国家开发银行香港分行, 
      pid:YH******, 
      childList:[]
    }, 
    {
      id=YH*****1, 
      name=国家开发银行广东省分行, 
      pid=YH******, 
      childList=[]
    }, {
      id=YH*****2, 
      name=国家开发银行深圳分行, 
      pid=YH******, 
      childList=[]
    }
  ]}
}

按照思路,我们是要ul里面套li,li里面套ul,这样无限套用,所以在子组件里面这么写:

<li>
  <div>
   <i @click='toggle' v-if='isFolder' class="mui-icon iconfont" :class="[open?'icon-wenjianjia':'icon-wenjianjiaguanbi']"></i>
   <!--isFolder判断是否存在子级改变图标-->
   <i @click='toggle' class="mui-icon iconfont icon-wenjian" style="color: #00ccff" v-else></i>
   <!--这里用到的方法是给父组件传值,具体可看上一篇文章-->
   <span @click="propInstCode(model);propInstName(model)">
    {{model.name}}
   </span>
  </div>
  <ul v-show="open" v-if='isFolder'>
   <tree-menu v-for='cel in model.childList' :model='cel'></tree-menu>
  </ul>
 </li>

在官方文档里面强调了name属性,所以我们在开始还要定义name,这边的name用到的是上面的tree-menu:

export default {
  name: 'treeMenu',
  props: ['model'],
  components: {}
}

按照vue的思想,不操作Dom树,我们定义两个变量,一个显示隐藏子菜单(open),一个存不存子菜单修改图标(isFolder)。

data() {
   return {
    open: false,
    isFolder: true,
   }
 },

我是参照一篇文章编写的,在这一步说的是“利用vue计算属性动态改变isFolder的值,修改图标,判断存在不子级和子级长度”

computed: {
  isFolder() {
    return this.model.childTreeNode && this.model.childTreeNode.length
  }
}

这里就出现了个问题,会一直不停地报错:

vuejs使用递归组件实现树形目录的方法

找了很久的问题,结果我是这样解决的,去掉computed的计算属性,将其放到created里面:

created(){
   //将isFolder放在这里判断可以识别出最底层菜单,然后改变图标,放在computed的话会一直报错并识别不出最底层菜单改变样式
   this.isFolder = this.model.childList && this.model.childList.length;
  }

显示/隐藏事件

methods: {
   toggle: function() {
    if(this.isFolder){
     this.open = !this.open;
    }
   },
}

到这里就构造好树形目录的组件了,只要在相应的父组件里面调用就行了,完整代码如下:

父组件中引用

<ul class="tree_container" v-for="item in list">
  <my-menu-tree :model='item' :instType='this.instType'></my-menu-tree>
</ul>

子组件:

<template>
 <li>
  <div>
   <i @click='toggle' v-if='isFolder' class="mui-icon iconfont" :class="[open?'icon-wenjianjia':'icon-wenjianjiaguanbi']"></i>
   <!--isFolder判断是否存在子级改变图标-->
   <i @click='toggle' class="mui-icon iconfont icon-wenjian" style="color: #00ccff" v-else></i>
   <span @click="propInstCode(model);propInstName(model)">
    {{model.name}}
   </span>
  </div>
  <ul v-show="open" v-if='isFolder'>
   <tree-menu v-for='cel in model.childList' :model='cel'></tree-menu>
  </ul>
 </li>
</template>
<script type="text/javascript">
 import {bus} from '../../bus.js'
 export default {
  name: 'treeMenu',
  props: ['model','instType'],
  components: {},
  data() {
   return {
    open: false,
    isFolder: true,
   }
  },
  computed: {
  },
  methods: {
   toggle: function() {
    if(this.isFolder){
     this.open = !this.open;
    }
   },
   //通过总线将值传给父组件
   propInstCode:function (model) {
    //$emit触发当前实例事件
     bus.$emit('custTreeSay',this.model.id);
   },
   propInstName:function (model) {
    bus.$emit('custTreeSayName',this.model.name);
   }
  },
  created(){
   //将isFolder放在这里判断可以识别出最底层菜单,然后改变图标,放在computed的话会一直报错并识别不出最底层菜单改变样式
   this.isFolder = this.model.childList && this.model.childList.length;
  }
 }
</script>

<style lang="less" rel="stylesheet/less" scoped>
 ul {
  list-style: none;
  padding-left: 20px;
 }
 ul li{
  list-style: none;
 }
 a{
  color: #404040;
  //text-decoration: underline;
 }
 i.icon {
  display: inline-block;
  width: 15px;
  height: 15px;
  background-repeat: no-repeat;
  vertical-align: middle;
 }
 i{
  opacity: 0.8;
  color: #f0ad4e;
 }
 .tree-menu li {
  line-height: 1.5;
 }
</style>

子组件可以直接使用,样式也一起贴出来了,但是在父组件中也有点样式,就留给你们自己操作了,这个完整的代码里面还包括了上篇文章提到的组件传值的部分。

我的icon用的是阿里的iconfont,大家也可以百度搜一下

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery基础知识filter()和find()实例说明
Jul 06 Javascript
javascript设计模式 接口介绍
Jul 24 Javascript
javascript真的不难-回顾一下基础知识
Jan 15 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
Jan 23 Javascript
用JavaScript修改CSS属性的代码
May 06 Javascript
jQuery 复合选择器应用的几个例子
Sep 11 Javascript
完美兼容各大浏览器的jQuery插件实现图片切换特效
Dec 12 Javascript
JS中关于事件处理函数名后面是否带括号的问题
Nov 16 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
Nov 23 Javascript
JS尾递归的实现方法及代码优化技巧
Jan 19 Javascript
微信小程序绘制半圆(弧形)进度条
Nov 18 Javascript
vue3如何优雅的实现移动端登录注册模块
Mar 29 Vue.js
Easy UI动态树点击文字实现展开关闭功能
Sep 30 #Javascript
js实现轮播图的两种方式(构造函数、面向对象)
Sep 30 #Javascript
React实践之Tree组件的使用方法
Sep 30 #Javascript
JS动态添加的div点击跳转到另一页面实现代码
Sep 30 #Javascript
Node.js微信 access_token ( jsapi_ticket ) 存取与刷新的示例
Sep 30 #Javascript
jqgrid实现简单的单行编辑功能
Sep 30 #Javascript
微信小程序富文本渲染引擎的详解
Sep 30 #Javascript
You might like
在服务端进行目录建立、删除,文件上传、删除的过程的php代码
2008/09/10 PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
smarty半小时快速上手入门教程
2014/10/27 PHP
Vagrant(WSL)+PHPStorm+Xdebu 断点调试环境搭建
2019/12/13 PHP
jQuery EasyUI API 中文文档 - ComboBox组合框
2011/10/07 Javascript
Firefox/Chrome/Safari的中可直接使用$/$$函数进行调试
2012/02/13 Javascript
JQuery入门—编写一个简单的JQuery应用案例
2013/01/03 Javascript
Js 冒泡事件阻止实现代码
2013/01/27 Javascript
基于Unit PNG Fix.js有时候在ie6下不正常的解决办法
2013/06/26 Javascript
jQuery使用load()方法载入另外一个网页文件内的指定标签内容到div标签的方法
2015/03/25 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
jquery实现先淡出再折叠收起的动画效果
2015/08/07 Javascript
基于BootStrap Metronic开发框架经验小结【二】列表分页处理和插件JSTree的使用
2016/05/12 Javascript
jquery判断checkbox是否选中及改变checkbox状态的实现方法
2016/05/26 Javascript
bootstrap日历插件datetimepicker使用方法
2016/12/14 Javascript
BootStrap栅格系统、表单样式与按钮样式源码解析
2017/01/20 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
AngularJS封装$http.post()实例详解
2017/05/06 Javascript
Vue.js实现的表格增加删除demo示例
2018/05/22 Javascript
express.js中间件说明详解
2019/03/19 Javascript
[04:22]DOTA2大事件之护国神翼
2020/08/14 DOTA
python通过urllib2爬网页上种子下载示例
2014/02/24 Python
python使用PythonMagick将jpg图片转换成ico图片的方法
2015/03/26 Python
python实现聚类算法原理
2018/02/12 Python
python队列queue模块详解
2018/04/27 Python
python爬取cnvd漏洞库信息的实例
2019/02/14 Python
pandas DataFrame 行列索引及值的获取的方法
2019/07/02 Python
Python 的字典(Dict)是如何存储的
2019/07/05 Python
linux下python中文乱码解决方案详解
2019/08/28 Python
DJANGO-URL反向解析REVERSE实例讲解
2019/10/25 Python
北美领先的牛仔品牌:Buffalo David Bitton
2017/05/22 全球购物
几道PHP的面试题
2012/05/19 面试题
竞聘书怎么写,如何写?
2014/03/31 职场文书
诚实守信道德模范事迹材料
2014/08/15 职场文书
简历中自我评价范文
2015/03/11 职场文书
中国梦宣传标语口号
2015/12/26 职场文书