iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue tree封装一个可选的树组件方式
  • 402
分享到

vue tree封装一个可选的树组件方式

2024-04-02 19:04:59 402人浏览 安东尼
摘要

目录组件实现的基本功能先看效果图组件实现的基本功能 1,根据后端返回的数据格式,传入组件动态的渲染出当前角色有哪些权限(新建,修改) 2,适配有2级和只有一级多选的数据 3,有全选(

组件实现的基本功能

1,根据后端返回的数据格式,传入组件动态的渲染出当前角色有哪些权限(新建,修改)

2,适配有2级和只有一级多选的数据

3,有全选(√) ,全不选 ,部分已选(-)的3装状态,每一级都支持(用的iview2次封装)

4,改变之后返回当前选中的所有权限的id,用于提交

5,手风琴效果,小屏适配

先看效果图

有部分权限没打开

关闭状态

打开

在这里插入图片描述

小屏

在这里插入图片描述

权限数据结构,select_status=1表示选中

在这里插入图片描述

默认添加没有权限的初始数据结构

在这里插入图片描述

有些数据只有一级子菜单,有些有两级

核心代码.Vue

<template>
  <div class="powerList">
    <div v-for="(item,index) in powers" :key="item.id" :class="{item:true,active:item.active}">
      <Checkbox :indeterminate="item.indeterminate" :value="item.val1" @click.prevent.native="handleCheckAll(index)">
        <span style="color:#1C213A;font-weight:600;">&nbsp;{{item.name}}</span>
      </Checkbox>
      <div style="font-size:30px;float:right;width:220px;cursor: pointer;color:#BEC1C8;text-align:right;" @click="open(item.active,index)">
        <Icon :type="item.active? 'md-arrow-dropup': 'md-arrow-dropdown'" />
      </div>
      <!-- 全部都是只有一级子菜单的 -->
      <CheckboxGroup v-if="oneChild(item.child)" v-model="item.checked" @on-change="checkGroupChange($event,index)">
        <Checkbox v-for="item2 in item.child" :key='item2.id' :label="item2.id">{{item2.name}}</Checkbox>
      </CheckboxGroup>
      <template v-else>
        <div v-for='(item3,index3) in item.child' :key="item3.id" class="item3">
          <!-- 有二级子菜单的 -->
          <template v-if="item3.child">
            <Checkbox :indeterminate="item3.indeterminate" :value="item3.val1" @click.prevent.native="level2CheckAll(index,index3)">&nbsp;{{item3.name}}</Checkbox>
            <CheckboxGroup v-model="item3.checked" @on-change='checkGroupChange($event,index,index3)'>
              <Checkbox v-for="item4 in item3.child" :key='item4.id' :label="item4.id">{{item4.name}}</Checkbox>
            </CheckboxGroup>
          </template>
        </div>
      </template>
    </div>
  </div>
</template>
<script>

export default {
  props: {
    powerData: Array
  },
  data () {
    return {
      powers: []
    }
  },
  watch: {
    powerData: {
      handler (val, old) {
        if (val && val.length && JSON.stringify(val) !== jsON.stringify(old)) {
          this.powers = this.fORMatData(val)
          this.save([...this.powers])
        }
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    // 保存返回选中的项的数组
    save (arr) {
      let auth_id = []
      arr.forEach(item => {
        if (item.indeterminate || item.val1) {
          auth_id.push(item.id)
          if (this.oneChild(item.child)) {
            auth_id = auth_id.concat([...item.checked])
          } else {
            item.child.forEach(item2 => {
              if (item2.indeterminate || item2.val1) {
                auth_id.push(item2.id)
                auth_id = auth_id.concat([...item2.checked])
              }
            })
          }
        }
      })
      console.log(auth_id)
      this.$emit('change', auth_id)
    },
    //把获取到的权限格式化成需要的格式
    
    formatData (arr) {
      return arr.map(item => {
        item.active = false //用于开关下拉
        if (!this.oneChild(item.child)) { // 有多级子菜单
          let total = 0 //计算当前项下的底级子菜单的总数 用于给主一级全选相应的状态
          item.child.map(item => item.child.length).forEach(item => {
            total += item
          })
          item.total = total
          item.child = item.child.map(item2 => {
            item2.checked = item2.child.filter(item3 => item3.select_status === 1).map(item4 => item4.id)
            if (item2.checked.length === item2.child.length) { //选中的子选项数量等于子选项数量 就是全选
              item2.indeterminate = false
              item2.val1 = true
            } else if (item2.checked.length === 0) { // 没有选中的
              item2.indeterminate = false
              item2.val1 = false
            } else { //<
              item2.indeterminate = true
              item2.val1 = false
            }
            return item2
          })
          this.changeLevel1Status(item) // 设置一级全选的状态
        } else { // 只有一级子菜单的
          item.checked = item.child.filter(item => item.select_status === 1).map(item => item.id) //子菜单当前选中的值
          let childNum = item.child.length
          let checkedNum = item.child.filter(item5 => item5.select_status === 1).length
          if (checkedNum === 0) {
            item.indeterminate = false
            item.val1 = false
          } else if (checkedNum < childNum) {
            item.indeterminate = true
            item.val1 = false
          } else {
            item.indeterminate = false
            item.val1 = true
          }
        }
        return item
      })
    },
    // 权限展开,手风琴
    open (val, index) {
      // 关闭所有的
      this.powers = this.powers.map(item => {
        item.active = false
        return item
      })
      let obj = this.powers[index]
      obj.active = !val
      // 打开点击的
      this.powers.splice(index, 1, obj)
    },
    // 只有一级子菜单的
    oneChild (arr) {
      return arr.every(item => item.child === undefined)
    },
    
    handleCheckAll (index) {
      if (this.oneChild(this.powers[index].child)) { //只有一级子菜单的
        let powers = [...this.powers]
        let obj = powers[index]
        if (obj.indeterminate) { //当前项有子菜单选中的
          obj.val1 = false;
        } else {
          obj.val1 = !obj.val1
        }
        obj.indeterminate = false;
        if (obj.val1) { // 如果是全选
          obj.checked = obj.child.map(item => item.id);
        } else {
          obj.checked = [];
        }
        this.powers = [...powers]
        this.save([...this.powers])
      } else {
        this.checkAllOther(index)
      }
    },
    // 有多级子菜单的全选
    checkAllOther (index) {
      let powers = [...this.powers]
      if (powers[index].indeterminate) { //当前项有子菜单选中的
        powers[index].val1 = false;
      } else {
        powers[index].val1 = !powers[index].val1
      }
      powers[index].indeterminate = false;
      if (powers[index].val1) { // 如果是全选
        powers[index].child.forEach(item => {
          item.val1 = true // 所有2级全选选中
          item.indeterminate = false //状态去掉
          item.checked = item.child.map(item2 => item2.id) //2级全选的子菜单都选中
        })
      } else {
        powers[index].child.forEach(item => {
          item.val1 = false
          item.checked = [];
          item.indeterminate = false //状态去掉
        })
      }
      this.powers = [...powers]
      this.save([...this.powers])
    },
    // 子菜单的checkGrounp改变,data选中的项的id构成的arr
    checkGroupChange (data, index, index3) {
      let powers = [...this.powers]
      let obj = index3 === undefined ? powers[index] : powers[index].child[index3]// 有index3就是二级子菜单的checkGroup
      if (data.length === obj.child.length) { //全部勾选
        obj.indeterminate = false;
        obj.val1 = true;
      } else if (data.length > 0) { //有选中的
        obj.indeterminate = true;
        obj.val1 = false;
      } else { //没选中的
        obj.indeterminate = false;
        obj.val1 = false;
      }
      // 有二级子菜单的项改变的时候
      if (index3 !== undefined) {
        this.changeLevel1Status(powers[index])
      }
      this.powers = [...powers]
      this.save([...this.powers])
    },
    // 2级的全选
    level2CheckAll (index, index3) {
      let powers = [...this.powers]
      let obj = powers[index].child[index3] //当前操作的2级全选
      if (obj.indeterminate) { //当前项有子菜单选中的
        obj.val1 = false;
      } else {
        obj.val1 = !obj.val1
      }
      obj.indeterminate = false;
      if (obj.val1) { // 如果是全选
        obj.checked = obj.child.map(item => item.id);
      } else {
        obj.checked = [];
      }
      this.changeLevel1Status(powers[index])
      this.powers = [...powers]
      this.save([...this.powers])
    },
    // 二级子菜单或2级全选时更改一级全选的状态
    changeLevel1Status (obj) {
      let checkedNum = 0
      obj.child.map(item => item.checked.length).forEach(item => {
        checkedNum += item
      })
      if (checkedNum === 0) {
        obj.indeterminate = false
        obj.val1 = false
      } else if (checkedNum < obj.total) {
        obj.indeterminate = true
        obj.val1 = false
      } else {
        obj.indeterminate = false
        obj.val1 = true
      }
    }
  },
}
</script>

<style lang="sCSS" scoped>
.powerList {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  .item {
    width: 370px;
    height: 58px;
    background: #f9f9f9;
    line-height: 58px;
    margin-bottom: 20px;
    padding: 0 10px 0 20px;
    overflow: hidden;
    &.active {
      height: auto;
    }
    /deep/ .ivu-checkbox-group label {
      display: block;
    }
    .item3 {
      /deep/ .ivu-checkbox-group {
        padding-left: 20px;
        label {
          display: inline-block;
        }
      }
    }
  }
}
</style>

核心代码主要就是数据的处理,底级的更改都触发上一级的状态和值得改变

用的时候主要就是一个props传入数据, 一个方法返回给父组件选中的值

<power :powerData='powers' @change="powerChange" />

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。 

--结束END--

本文标题: vue tree封装一个可选的树组件方式

本文链接: https://www.lsjlt.com/news/144389.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue tree封装一个可选的树组件方式
    目录组件实现的基本功能先看效果图组件实现的基本功能 1,根据后端返回的数据格式,传入组件动态的渲染出当前角色有哪些权限(新建,修改) 2,适配有2级和只有一级多选的数据 3,有全选(...
    99+
    2024-04-02
  • Vue封装一个Tabbar组件 带组件路由跳转方式
    目录Vue封装Tabbar组件在App.vue 封装 路由跳转 利用router-view的特性子组件Tabbar然后就是配置的路由从零开始封装一个Tabbar首先底部菜单栏最外层是...
    99+
    2024-04-02
  • 开发一个封装iframe的vue组件
    目录一、组件介绍 二、组件内部结构及逻辑 1、代码组织结构2、地图组件三、iframe接口 四、外部接口 五、运行结果六、总结 VUE的基本组成单元,我看应该是组件。用VUE开发前端...
    99+
    2024-04-02
  • vue封装一个弹幕组件详解
    目录前言功能实现1、获取随机颜色随机数生成随机颜色编码生成2、随机生成弹幕出现的高度坐标3、格式化弹幕对象颜色定位4、创建弹幕对象滚动动画定义创建弹幕dom对象实例弹幕销毁弹幕循环5...
    99+
    2022-11-13
    vue封装弹幕组件 vue封装组件
  • 如何开发一个封装iframe的vue组件
    这篇文章给大家分享的是有关如何开发一个封装iframe的vue组件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。VUE的基本组成单元,我看应该是组件。用VUE开发前端项目,就是开发一个个组件,然后搭积木一样,将项...
    99+
    2023-06-14
  • vue中使用render封装一个select组件
    目录使用render封装一个select组件vue另类封装--render函数封装先看看文件的结构render函数封装使用render封装一个select组件 父组件 val...
    99+
    2024-04-02
  • vue封装一个图案手势锁组件
    目录说在前面效果展示预览地址实现步骤1.组件设计2.组件分析3.组件实现4.组件使用组件库引用源码地址组件文档说在前面 现在很多人都喜欢使用图案手势锁,这里我使用vue来封装了一个可...
    99+
    2024-04-02
  • vue二次封装一个高频可复用组件的全过程
    目录前言继承原有组件接口v-model插槽组件更抽象总结前言 在我们的业务里,我们通常会二次封装一些高频业务组件,比如弹框,抽屉,表单等这些业务组件,为什么要二次封装?我们所有人心里...
    99+
    2022-11-13
    vue如何二次封装组件 vue组件封装并复用 vue的组件复用机制
  • vue中怎么封装一个弹出框组件
    这期内容当中小编将会给大家带来有关vue中怎么封装一个弹出框组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.你需要先建一个弹出框的模板://首先创建一个mack.v...
    99+
    2024-04-02
  • Vue实现封装一个切片上传组件
    目录组件效果使用文档封装过程1. 文件切片2. 构造切片请求参数3. 控制分片请求的并发完整代码待完善组件效果 单文件切片上传 多文件切片上传 组件使用案例 <templa...
    99+
    2023-03-19
    Vue封装切片上传组件 Vue切片上传组件 Vue切片上传
  • vue 封装一个高质量的表单通用组件
    目录正文基于Element-plus实现二次封装表单组件步骤1步骤2富文本表单项封装上传表单项封装同行多个表单布局封装步骤3总结正文 我们都知道表单组件应该是后台管理系统中用得最多...
    99+
    2023-03-10
    vue 封装表单通用组件 vue 封装表单
  • 怎么封装一个vue中也可使用的uniapp全局弹窗组件
    这篇文章主要介绍了怎么封装一个vue中也可使用的uniapp全局弹窗组件的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么封装一个vue中也可使用的uniapp全局弹窗组件文章都会有所收获,下面我们一起来看看吧...
    99+
    2023-07-05
  • Vue分页组件的封装方法
    前言 这个是基于vue2的分页封装,仿照elementUI而写的组件。 效果如图 话不多说,直接上代码 <template>   <div class="pagi...
    99+
    2024-04-02
  • vue日历组件的封装方法
    本文实例为大家分享了vue日历组件的封装代码,供大家参考,具体内容如下 图示 封装的组件的代码如下 <template>   <div class="calend...
    99+
    2024-04-02
  • 怎么封装一个vue自定义日历组件
    这篇文章主要介绍“怎么封装一个vue自定义日历组件”,在日常操作中,相信很多人在怎么封装一个vue自定义日历组件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么封装一个vue自定义日历组件”的疑惑有所帮助!...
    99+
    2023-07-05
  • vue左右滑动选择日期组件封装的方法
    现在做的项目中遇到了左右滑动选择日期的一个功能,然后我封装了一下这个组件,现在分享给大家看一下: 效果图: 1、安装dayjs日期文件 npm install dayjs --sa...
    99+
    2024-04-02
  • vue 的全选组件封装你知道多少
    效果  封装的组件 <template> <el-form-item :label="label"> <el-checkbox ...
    99+
    2024-04-02
  • vue中全选组件封装的示例分析
    这篇文章将为大家详细讲解有关vue中全选组件封装的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。效果 封装的组件<template>  <el-fo...
    99+
    2023-06-29
  • vue如何封装div框选时间的组件
    这篇文章主要为大家展示了“vue如何封装div框选时间的组件”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue如何封装div框选时间的组件”这篇文章吧。div...
    99+
    2024-04-02
  • 基于Vue如何封装一个虚拟列表组件
    今天小编给大家分享一下基于Vue如何封装一个虚拟列表组件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。组件效果使用方法<...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作