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 相关文章推荐
论坛里点击别人帖子下面的回复,回复标题变成“回复 24# 的帖子”
Jun 14 Javascript
JavaScript传递变量: 值传递?引用传递?
Feb 22 Javascript
javascript继承之为什么要继承
Nov 10 Javascript
javascript获取隐藏dom的宽高 具体实现
Jul 14 Javascript
使用js写的一个简易的投票
Nov 27 Javascript
表单验证正则表达式实例代码详解
Nov 09 Javascript
微信小程序 时间格式化(util.formatTime(new Date))详解
Nov 16 Javascript
jquery编写日期选择器
Mar 16 Javascript
详解vue-router 动态路由下子页面多页共活的解决方案
Dec 22 Javascript
jQuery 选择器用法基础入门示例
Jan 04 jQuery
vue项目中js-cookie的使用存储token操作
Nov 13 Javascript
使用vue编写h5公众号跳转小程序的实现代码
Nov 27 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
基于数据库的在线人数,日访问量等统计
2006/10/09 PHP
PHP获取url的函数代码
2011/08/02 PHP
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
php提取身份证号码中的生日日期以及验证是否为成年人的函数
2015/09/29 PHP
PHP数组array类常见操作示例
2020/05/15 PHP
xtree.js 代码
2007/03/13 Javascript
让Firefox支持event对象实现代码
2009/11/07 Javascript
jquery验证表单中的单选与多选实例
2013/08/18 Javascript
ECMAScript6函数剩余参数(Rest Parameters)
2015/06/12 Javascript
jQuery简单实现页面元素置顶时悬浮效果示例
2016/08/01 Javascript
jquery实现侧边栏左右伸缩效果的示例
2017/12/19 jQuery
layui表格内容溢出的解决方法
2019/09/06 Javascript
实例分析javascript中的异步
2020/06/02 Javascript
解决Vue中的生命周期beforeDestory不触发的问题
2020/07/21 Javascript
[18:32]DOTA2 HEROS教学视频教你分分钟做大人-谜团
2014/06/12 DOTA
给Python的Django框架下搭建的BLOG添加RSS功能的教程
2015/04/08 Python
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
python3 kmp 字符串匹配的方法
2018/07/07 Python
python多进程实现文件下载传输功能
2018/07/28 Python
numpy基础教程之np.linalg
2019/02/12 Python
Python 抓取微信公众号账号信息的方法
2019/06/14 Python
python 日志 logging模块详细解析
2020/03/31 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
python如何求100以内的素数
2020/05/27 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
HTML5 canvas基本绘图之文字渲染
2016/06/27 HTML / CSS
浅谈Html5中视频 音频标签 进度条的问题
2016/07/26 HTML / CSS
北京华建集团SQL面试题
2014/06/03 面试题
租车协议书范本
2014/04/22 职场文书
教师考核评语
2014/04/28 职场文书
以幸福为主题的活动方案
2014/08/22 职场文书
2014年综治维稳工作总结
2014/11/17 职场文书
2014年班组长工作总结
2014/11/20 职场文书
2015年办公室主任工作总结
2015/04/09 职场文书
你对自己的信用报告有过了解吗?
2019/07/09 职场文书
Redis+Lua脚本实现计数器接口防刷功能(升级版)
2022/02/12 Redis