vue单个组件实现无限层级多选菜单功能

wTree.vue 

原理:每一个多选框都是一个节点,每个节点就是一个wTree组件,有父级(顶级level为0),有子级(底层list[]是空的),组件之间状态传递是通过组件通信传递,对于外部数据checkList数组的修改是通过store实现的。初始化从底层状态传递到上层,一层一层传递。改变状态,不同状态改变,修改checklist数组。大概就这个思路,下面是代码:

<template>
 <div>
 <div >
 <span v-for="o in levelNum"> </span>
 <i v-if="item.list" :class="open ? openClass : closeClass" @click="showSub" style="color: #00d6b2"></i>
 <span v-else> </span>
 <span>
 <a @click="changeState">
  <img src="./../assets/selectedAll.png" v-if="selectedState === 'all'" width="15px" height="15px"/>
  <img src="./../assets/selectedSub.png" v-if="selectedState === 'sub'" width="15px" height="15px"/>
  <img src="./../assets/selectedNull.png" v-if="selectedState === 'null'" width="15px" height="15px"/>
 </a>
 </span>
 <span>{{item.name}}</span>
 </div>
 <component v-show="open" :is="node" :item="o" :state="stateSub" v-for="o of item.list" :key="o.key" :level="levelNum" v-on:changeToPar="changeBySub">
 </component>
 </div>
</template>
<script>
 export default {
 name: 'wTree',
 props: ['item', 'level', 'state'],
 data () {
 return {
 open: true,
 node: 'wTree', // 控制菜单开关的
 selected: false, // 选中的情况下
 selectedState: 'null', // 子组件被选中的情况下向上传递all/sub/null
 originInfo: 'create', // 组件信息源,create/parent/children/this
 openClass: 'el-icon-caret-bottom',
 closeClass: 'el-icon-caret-right',
 selectClass: 'el-icon-check',
 selectBg: '#1c8de0',
 list: [],
 createSwitch: true
 }
 },
 computed: {
 levelNum () {
 return (this.level + 1)
 },
 stateSub () {
 return {
  selected: this.selected,
  originInfo: this.originInfo
 }
 }
 },
 methods: {
 showSub () {
 this.open = !this.open
 },
 changeState () {
 if (this.selected) {
  this.selected = false
  this.selectedState = 'null'
  this.originInfo = 'this'
  for (let o of this.list) {
  o.selectedState = 'null'
  }
 } else {
  this.selected = true
  this.selectedState = 'all'
  this.originInfo = 'this'
  for (let o of this.list) {
  o.selectedState = 'all'
  }
 }
 let data = {
  id: this.item.menuId,
  selectedState: this.selectedState,
  originInfo: 'parent'
 }
 this.$emit('changeToPar', data)
 },
 changeBySub (data) {
 // 如果是父组件true,判断状态,未被选中,添加id到list,selectSub=true,通知父组件,添加store的数组中,选中通知父组件,this.list.length=this.length状态改为selected
 // 修改自身状态,添加list
 let temp = data
 if (data.originInfo === 'create') {
  this.list.push(data)
 } else {
  this.originInfo = 'parent'
  let stateNull = 'null'
  let stateAll = 'all'
  let stateSub = 'sub'
  for (let o of this.list) {
  if (o.id === temp.id) {
  o.selectedState = temp.selectedState
  } 

  if (o.selectedState !== 'all') {
  stateAll = null
  }
  if (o.selectedState !== 'null') {
  stateNull = null
  }
  }
  if (stateNull) {
  this.selectedState = stateNull
  this.selected = false
  } else if (stateAll) {
  this.selectedState = stateAll
  this.selected = true
  } else {
  this.selectedState = stateSub
  this.selected = true
  }
  let data = {
  id: this.item.menuId,
  selectedState: this.selectedState,
  originInfo: 'parent'
  }
  this.$emit('changeToPar', data)
 }
 }
 },
 watch: {
 selected () {
 // 初始化
 if (this.originInfo === 'create') {
  // 不改变值
 } else {
  // 改变值********
  if (this.selected) {
  // 添加值
  this.$store.commit('PUSH_CHECK_LIST', this.item.menuId)
  } else {
  // 删除值
  this.$store.commit('SPLICE_CHECK_LIST', this.item.menuId)
  }
 }
 },
 state () {
 // 子组件得到通知,如果状态一直,不去改变,如果状态不一致改变
 if (this.state.originInfo === 'this') {
  this.originInfo = 'this'
 }
 if (this.originInfo === 'create') {
  this.originInfo = 'children'
 } else {
  if (this.state.originInfo !== 'parent') {
  if (this.state.selected) {
  this.selected = true
  this.selectedState = 'all'
  if (this.list !== []) {
  for (let o of this.list) {
   o.selectedState = 'all'
  }
  }
  } else {
  this.selected = false
  this.selectedState = 'null'
  if (this.list !== []) {
  for (let o of this.list) {
   o.selectedState = 'null'
  }
  }
  }
  }
 }
 },
 list () {
 // 初始化数组
 if (this.list.length === this.item.list.length) {
  let stateNull = 'null'
  let stateAll = 'all'
  let stateSub = 'sub'
  for (let o of this.list) {
  if (o.selectedState !== 'all') {
  stateAll = null
  }
  if (o.selectedState !== 'null') {
  stateNull = null
  }
  }
  if (stateNull) {
  this.selectedState = stateNull
  this.selected = false
  } else if (stateAll) {
  this.selectedState = stateAll
  this.selected = true
  } else {
  this.selectedState = stateSub
  this.selected = true
  }
  let data = {
  id: this.item.menuId,
  selectedState: this.selectedState,
  originInfo: 'create'
  }
  this.$emit('changeToPar', data)
 }
 }
 },
 created () {
 // 初始化,把每个组件,从最底层添加到节点列表中,这样每个子组件都在list中了,就是originInfo=create的情况下添加数组,就不用判断数组长度,直接改变状态
 if (this.createSwitch) {
 let i = this.$store.state.checkList.indexOf(this.item.menuId)
 console.log(!this.item.list)
 console.log('-----------------------初始化')
 if (!this.item.list) {
  if (i > -1) {
  this.selectedState = 'all'
  this.selected = true
  } else {
  this.selectedState = 'null'
  this.selected = false
  } 

  let data = {
  id: this.item.menuId,
  selectedState: this.selectedState,
  originInfo: 'create'
  }
  this.$emit('changeToPar', data)
  this.originInfo = 'this'
 }
 this.createSwitch = false
 }
 console.log(this.state)
 console.log('----------------created')
 },
 updated () {
 console.log('-------updated=======')
 let i = this.$store.state.checkList.indexOf(this.item.menuId)
 console.log(!this.item.list)
 console.log('-----------------------初始化')
 if (!this.item.list) {
 if (i > -1) {
  this.selectedState = 'all'
  this.selected = true
 } else {
  this.selectedState = 'null'
  this.selected = false
 } 

 let data = {
  id: this.item.menuId,
  selectedState: this.selectedState,
  originInfo: 'parent'
 }
 this.$emit('changeToPar', data)
 this.originInfo = 'this'
 }
 },
 mounted () {
 console.log('=========mounted-----')
 }
 }
</script> 

调用 orgList带有层级的json数组

<w-tree v-for="o of orgList" :item="o" :level="0" :key="o.key"></w-tree> 

总结

以上所述是小编给大家介绍vue单个组件实现无限层级多选菜单,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

您可能感兴趣的文章:

  • vue多级多选菜单组件开发
(0)

相关推荐

  • vue多级多选菜单组件开发

    本文实例为大家分享了vue多级多选菜单组件的制作方法,供大家参考,具体内容如下 要开发一个这样的多级多选菜单组件,功能是: 点击父标题栏可以打开与折叠子列表 点击父标题栏的勾选图标可以全选或取消子列表 点击子列表的勾选图标达到全选时,父标题栏的勾选图标自动勾选:反之,没达到全选时,父标题栏的勾选图标自动取消勾选 当所有父标题栏的勾选图标达到全选时,最底下那个全选框自动勾选:反之,没达到全选时,最底下那个全选框自动取消勾选 点击最底下那个全选框可以全选或取消全部的勾选图标 所以总结起来我们重点要利

  • vue单个组件实现无限层级多选菜单功能

    wTree.vue  原理:每一个多选框都是一个节点,每个节点就是一个wTree组件,有父级(顶级level为0),有子级(底层list[]是空的),组件之间状态传递是通过组件通信传递,对于外部数据checkList数组的修改是通过store实现的.初始化从底层状态传递到上层,一层一层传递.改变状态,不同状态改变,修改checklist数组.大概就这个思路,下面是代码: <template> <div> <div > <span v-for="o in

  • vue基于element-ui的三级CheckBox复选框功能的实现代码

    最近vue项目需要用到三级CheckBox复选框,需要实现全选反选不确定三种状态.但是element-ui table只支持多选行,并不能支持三级及以上的多选,下面通过本文给大家讲解实现方法. 效果图预览: 首先是页面布局,当然也可已使用table,但是自己用flex布局后面更容易增删改查其他功能 <div class="deliverySetting-table"> <div class="table-head"> <div clas

  • 微信小程序组件开发之可视化电影选座功能

    目录 一. 简介 1. 组件数据 2. 组件页面布局 1. 标识区构成 2.座位区构成 2.1 电影屏幕: 2.2 电影厅介绍: 2.3 座位区域: 3. 组件业务逻辑 总结 一. 简介 想必很多人都有陪男女朋友去看电影的经历吧,是不是在每次选座的时候你都要征求女盆友或男盆友的意见,什么?不征求?!那你完了! 目前市场上许多的电影购票app和小程序中,为了让观众老爷们在线上更好地选择自己心怡的位置,方便可视化的选座数据必不可少,在此, 让我们一起来看看这个好用的可视化选座组件吧! 视图效果如下:

  • 快速修改antd vue单个组件的默认样式

    目录 一.想要修改组件的默认样式 二.类名scoped的限制 你是否会有这样的疑惑 三.使用/deep/. >>>时 Ant Design Vue地址:https://www.antdv.com/docs/vue/introduce-cn/ 刚接触Ant Design Vue的童鞋们可能会有这样的问题,不就是修改默认的组件样式吗,为什么一会生效,一会又不生效.希望看完这个文章,会给你一些收获~ 一.想要修改组件的默认样式 首先你需要知道组件是渲染在哪里的 这个组件是渲染在当前页面内部,还

  • Vue实现美团app的影院推荐选座功能【推荐】

    经常用美团app买电影票,不禁对它的推荐选座功能产生了好奇,于是打算自己实现一个类似的算法,美团app的推荐选座界面如下 最多可以选5个座位,本demo的选座界面如下图 上图是点击 推荐选座5人 后选出的座位(绿色),这个demo和美团app不同的地方在于可以连续进行推荐选座,美团app点击了推荐选座就必须买票才能继续选择. 本demo采用Vue-cli搭建,github地址点此 ,clone后直接npm start即可进行具体操作 算法思考过程 对于这个推荐座位算法,我尝试了不同场次的电影进行

  • VUE 无限层级树形数据结构显示的实现

    目录 组件递归调用 使用render方法 在做项目中,会遇到一些树形的数据结构,常用在左侧菜单导航,或者评论引用等地方,这种数据结构有个特点是不知道它会嵌套多少层,所以用template去展示这样的数据时就有点棘手,这篇文章梳理两种展示这种数据结构的方法. 文章中用到的数据是下面这个: mainData: { value: "root", children:[{ value: "层级1-1", children:[{ value: "层级2-1"

  • vue+el-menu实现菜单栏无限多层级分类

    本文实例为大家分享了vue+el-menu实现菜单栏无限多层级分类的具体代码,供大家参考,具体内容如下 思路:数据格式须为数组内部多层嵌套模式,利用递归渲染菜单栏数据实现菜单多层级分类. 1.模拟菜单数据,引入封装组件 <template>   <div class="container">     <el-container>       <el-header>Header</el-header>       <el-

  • Vue.js组件通信的几种姿势

    写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址: https://github.com/answershuto/learnVue . 在学习过程中,为Vue加上了中文的注释 https://github.com/answershuto/learnVue/tree/master/vue-src ,希望可以对其他想学习Vue源码的小伙伴有所帮助. 可能会有理解存在偏差的地方,欢迎提issu

  • Vue.js实现无限加载与分页功能开发

    本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景--分页/无限加载,帮助读者更好的理解Vue.js中的一些设计思想.与许多Todo List类的入门教程相比,更全面的展示使用Vue.js完成一个需求的思考过程:与一些构建大型应用的高阶教程相比,又更专注于一些零碎细节的实现,方便读者快速掌握.致用. 需求分析 当一个页面中信息量过大时(例如一个新闻列表中有200条新闻需要展示),就会产生问题,例如: >数据量过大,影响加载速度 >用户体验差,很难定位到之前自己看过的某篇文章 >

随机推荐