Vue element-ui el-cascader 只能末级多选问题

目录
  • element-ui el-cascader只能末级多选
  • 扩展实现element-ui中el-cascader全选功能
    • 实现思路如下

element-ui el-cascader只能末级多选

像这样的需求我们直接可以用css完成

/deep/.el-cascader-panel:first-child .el-checkbox{
  display:none;
}

扩展实现element-ui中el-cascader全选功能

重所周知,element-ui中的cascader中,没有对所有子节点的全选功能。

近期,公司项目有一个功能是,如果点击了全选,则选中所有子节点的功能;如果在全选状态下,取消了任意一个节点,则移除该节点和全部节点;如果在全选状态下,又点击了全选,则完成全不选的操作,即实现效果如下

图1.1: 从【选中部分节点】(或【所有节点都没有选择】) 到【全选】的实现效果

图1.2 从【已选中全部节点】状态到【取消任意一个节点】效果图

图1.3 全不选效果图(在【全选】状态下再次点击【全选】按钮,或挨个取消已选中节点)

实现思路如下

【Ⅰ】返回数据格式

1. 如果是只有一层字节点,他的数据返回格式应是[节点1, 节点2, .....]

2. 如果含有多层节点,他的数据返回格式应该是[ [父节点,子节点,孙子节点...], [父节点,子节点,孙子节点...] ],这种数据返回格式,可以很清晰的看到各个节点所处的层次结构

【2】全选实现方式

1. 全选状态:包含了所有节点,因为数据结构层次的不确定,可以大致分为两种:

第一种,单层结构,对于全选实现方式很简单,通过更改绑定的数据源,加入所有节点即可;

第二种,多层结构,对于这种数据结构,我们采用递归的方式(不确定是2层,3层.还是更多),首先我们创建一个临时数据,用于保存根节点到各个子节点中所有节点的value值,对于如图所示的11号节点和8号节点,那我们应该保存的值为[ [1, 3, 7, 11], [1, 3, 8] ]

2. 全不选状态:

  • 对于这个状态比较简单,将数组清空即可

3. 从全选状态到取消任意一个节点状态:

  • 对于这个状态,删除【全选】所对应的节点和删除本次要移除的节点即可

组件源码奉上

<template>
  <div>
    <el-cascader
      v-model="select_options"
      ref="cascader"
      :options="options_cascader"
      :props="getProps"
      :filterable="filterable"
      @change="optionsChange"
      collapse-tags
      clearable></el-cascader>
  </div>
</template>
<script>
  import cloneDeep from "lodash/cloneDeep";

  export default {
    name: "myCascader",
    props: {
      options: { // 级联选择器选项
        type: Array,
        default: []
      },
      is_deep: { // 是否有children,即数据深度是否为多层
        type: Boolean,
        required: true
      },
      has_all_select: { // 是否为带有全部的选项
        type: Boolean,
        required: true
      },
      all_select_flag: { // '全部'选项的标识
        type: String | Number,
        default: ''
      },
      value: {  // 绑定的value值
        type: String,
        default: 'value'
      },
      label: { // 绑定了label值
        type: String,
        default: 'label'
      },
      filterable: { // 是否可以模糊搜索(只能选中最后一层子节点)
        type: Boolean,
        default: false
      }
    },
    mounted() {
      this.options_cascader = cloneDeep(this.options) // 深拷贝传过来的数据源,引用了lodash包
      if (!this.is_deep && this.has_all_select && !this.all_select_flag) {
        console.warn("当前为单层数据且含有全部选项,请输入全部选项标识,默认为'',如果全部类型的标识为''请忽略")
      }
    },
    data() {
      return {
        options_cascader: [], // 所有选项
        select_options: [], // 以选择的节点
        is_select_all: false, // 是否为全选
        deep_option_data: [] // 缓存各个深度的value
      }
    },
    computed: {
      // 获取配置选项
      getProps() {
        return {
          multiple: true,
          expandTrigger: 'hover',
          emitPath: this.is_deep,
          value: this.value,
          label: this.label
        }
      },
    },
    methods: {
      optionsChange() {
        // 判断已选中的节点中是否包含全部
        let has_all_option = false
        if (!this.is_deep) {
          has_all_option = this.select_options.includes(this.all_select_flag)
        } else {
          has_all_option = this.select_options.some(res => res.length === 1)
        }
        /**
         * 如果已选择节点中包含全部,且is_select_all为true时,代表移除了选项中除全部外的某个节点
         * 如果已选择节点中包含全部,且is_select_all为false时,代表选择了全部节点
         * 如果已选择节点中不包含全部,且is_select_all为true时,代表取消选择全部节点
         * */
        if (has_all_option && this.is_select_all) {
          this.$refs.cascader.$refs.panel.clearCheckedNodes()
          this.select_options.splice(this.searchSelectAllNodeIndex(), 1)
          this.is_select_all = false
        } else if (has_all_option && !this.is_select_all) {
          this.is_select_all = true
          this.selectAll()
        } else if (!has_all_option && this.is_select_all) {
          this.is_select_all = false
          this.$refs.cascader.$refs.panel.clearCheckedNodes()
          this.select_options = []
        }
        this.$emit('getOptions', this.select_options)
      },
      // 查找全部节点所在的索引
      searchSelectAllNodeIndex() {
        if (!this.is_deep) {
          return this.select_options.indexOf(this.all_select_flag)
        } else {
          let selectAllOptionIndex = -1
          this.select_options.forEach((res, index) => {
            if (res.length === 1) {
              selectAllOptionIndex = index
            }
          })
          return selectAllOptionIndex
        }
      },
      // 选择全部
      selectAll() {
        this.select_options = []
        if (!this.is_deep) {
          // 为单层数据,即没有children
          this.options_cascader.forEach(res => {
            this.select_options.push(res[this.value])
          })
        } else {
          // 多层数据, 递归
          this.getDeepOptions(this.options_cascader)
        }
      },
      // 递归获取深层数据
      getDeepOptions(value) {
        let arr
        value.forEach(res => {
          if (res.children) {
            // 如果不是最后一层,则缓存当前层次的value
            this.deep_option_data.push(res[this.value])
            this.getDeepOptions(res.children)
          } else {
            // 如果是最后一层,把最后一层的value放入级联选择器绑定的数组
            arr = cloneDeep(this.deep_option_data)
            arr.push(res[this.value])
            this.select_options.push(arr)
          }
        })
        // 每一层循环结束后,清空本层的父节点
        this.deep_option_data.pop()
      }
    }
  }
</script>

<style scoped>

</style>

使用方法

// 多层结构,带全部
<my-cascader
    :options="options"
    :is_deep="true"
    :has_all_select="true"
     @getOptions="getOptions">
</my-cascader>

// 单层结构,带全部
<my-cascader
    :options="options"
    :is_deep="false"
    :has_all_select="true"
     @getOptions="getOptions">
</my-cascader>

// 注:如果不需要配置全部节点则直接使用element提供的cascader即可
// 本组件只考虑第一层带有全部的情况,且全部节点不带有children属性,即只有一层,若除第一层节点外其他层次节点带有全部选项,则勾选本层次的上一层节点即可

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

(0)

相关推荐

  • 关于element ui中el-cascader的使用方式

    目录 element ui中el-cascader使用 例→ 代码 element中el-cascader使用及自定义key名 element ui中el-cascader使用 要想实现进入页面直接选中选择器中的选项 例→ 那v-model绑定的值必须是数组形式的!!(element ui官方文档中没提到这一点好像,我也是试了很多次才发现的) 代码 <el-form-item label="分类:" prop="region" class="regi

  • 浅谈Vue使用Cascader级联选择器数据回显中的坑

    业务场景 由于项目需求,需要对相关类目进行多选,类目数据量又特别大,业务逻辑是使用懒加载方式加载各级类目数据,编辑时回显用户选择的类目. 问题描述 使用Cascader级联选择器过程中主要存在的应用问题如下: 1.由于在未渲染节点数据的情况下编辑时无法找到对应的类目数据导致无法回显,如何自动全部加载已选择类目的相关节点数据: 2.提前加载数据后,点击相应父级节点出现数据重复等: 3.使用多个数据源相同的级联选择器,产生只能成功响应一个加载子级节点数据: 4.Vue中级联选择器相应数据完成加载,依

  • elementui中的el-cascader级联选择器的实践

    目录 一.效果 二.主要代码 一.效果 功能:使用接口调回来的数据,显示出可选的项,并开始有默认的选项值. 二.主要代码 <el-cascader ref="cascaderAddr" :options="rangeArr" :props="optionProps" v-model="plable" @change="handleChange3" style="width: 100%;&qu

  • 详解el Cascader懒加载数据回显示例

    正文 数据回显时保证 v-model props options 绑定的数据是正确的. 调用 props.lazyLoad 方法中的 resolve 回掉函数设置数据,示例来自el官网. 好多例子中说需要设置 options, 但是异步获取子节点,设置它是没有用的. <el-cascader :props="props"></el-cascader> <script> let id = 0 export default { data() { retu

  • 解决element ui cascader 动态加载回显问题

    elementui是基于vue2.0的组件库,专为开发人员.设计人员而设计的:可以快速搭建项目框架,集成了界面样式,先给大家介绍下element ui cascader 动态加载回显问题解决方法. props: { lazy: true, async lazyLoad(node, resolve) { } } 但是当我赋值给cascader的时候,cascader却不显示了.只要重新加载下cascader组件就行. <el-cascader v-if="isShowAddressInfo&

  • 关于element中el-cascader的使用方式

    目录 element中el-cascader的使用 使用el-cascader报错解决 一.options为空的情况 二.编辑时给cascader赋值 三.点击了父节点后改变了cascader的options element中el-cascader的使用 从后端拿到arr数据结构: cityList: [     {         id: 1,         name: '北京',         child: [             id: 11,             name:

  • Vue element-ui el-cascader 只能末级多选问题

    目录 element-ui el-cascader只能末级多选 扩展实现element-ui中el-cascader全选功能 实现思路如下 element-ui el-cascader只能末级多选 像这样的需求我们直接可以用css完成 /deep/.el-cascader-panel:first-child .el-checkbox{ display:none; } 扩展实现element-ui中el-cascader全选功能 重所周知,element-ui中的cascader中,没有对所有子节

  • Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)

    这篇博客主要介绍树形控件的两个小小的功能: 下拉菜单 输入过滤框 以CSS样式为主,也会涉及到Vue组件和element组件的使用. 对于没有层级的数据,我们可以使用表格或卡片来展示.要展示或建立层级关系,就一定会用到树形组件了. 使用Vue + Element UI,构建出最基本的树如下图所示: 现在我们就要在这个基础上进行改造,使页面更加符合我们的交互场景. 下拉菜单 将下拉菜单嵌到树节点中,使操作更加简便.紧凑. 效果演示 效果如图: 图示1:悬浮在树节点状态 图示2:点击三个点图标状态

  • vue Element UI扩展内容过长使用tooltip显示示

    目录 1. 介绍 2. element-ui(vue2版本) 2.1 注册指令 1) akTooltipAutoShow.js 2.2 使用 3. element-plus(vue3版本) 3.1 注册指令 1) akTooltipAutoShow.js 2) 进行局部或全局注册 3.2 使用 1. 介绍 Tooltip常用于展示鼠标 hover 时的提示信息. 而在实际过程中,有这么一个需求:只有文字内容排不下,出现省略号,才需要显示tooltip的提示内容. 本文章的思路是通过一个自定义指令

  • Vue + Element UI图片上传控件使用详解

    上一篇 Vue +Element UI +vue-quill-editor 富文本编辑器及插入图片自定义 主要是写了富文本编辑器的自定义及编辑器中图片的上传并插入到编辑内容,这篇文章单独介绍一下element UI 图片上传控件的使用.首先要安装element并中引入,安装引入过程这里不再赘述. 1.引用element 上传控件. <el-upload action="/mgr/common/imgUpload"//这里需要配置一下文件上传地址(跨域) list-type=&qu

  • vue element ui validate 主动触发错误提示操作

    elementUI使用了async-validator进行表单验证,但是当我使用下拉树(el-cascader)时,发现其不主动触发,于是我只能主动去触发,方法如下: this.$refs['form'].fields[0].validateMessage = 'error message' this.$refs['form'].fields[0].validateState = 'error' 补充知识:element-ui 打开页面触发校验问题 如果你设置了关闭弹出页就resetFields

  • Vue+Element ui 根据后台返回数据设置动态表头操作

    由于后端是多人开发,也没有规范数据格式,所有页面是我一个人开发,所以就会遇到同样的页面不同的返回数据格式问题. 一.根据element文档,利用prop属性绑定对应值,label绑定表头. html <el-table class="tb-edit" highlight-current-row :data="tableData" border style="width: 100%"> <template v-for="

  • vue + element ui实现播放器功能的实例代码

    没有效果图的展示都是空口无凭 1.基于audio并结合elementUI 的进度条实现 2.实现了播放器基本的功能,播放/暂停.快进.静音.调节声音大小.下载等功能 html代码,关键部分已加注释 <div class="right di main-wrap" v-loading="audio.waiting"> <!-- 此处的ref属性,可以很方便的在vue组件中通过 this.$refs.audio获取该dom元素 --> <au

  • 总结Vue Element UI使用中遇到的问题

    基于 vue2.0 的 element-ui 框架,使用起来还是很方便的,非常适合快速开发,但是在做自己的项目中还是会碰到这样那样的问题,有些问题官方文档并不是很详尽,以下是我在使用 element-ui 过程中一些常用的或碰到的一些问题笔记. 一.DateTimePicker 日期选择范围为当前时间以及当前时间之前 <template> <div> <el-date-picker size="small" clearable :picker-option

  • Vue+Element UI实现下拉菜单的封装

    本文实例为大家分享了Vue+Element UI实现下拉菜单封装的具体代码,供大家参考,具体内容如下 1.效果图 先贴个效果图,菜单项没有做样式美化,图中显示的边框也是没有的(边框是外部容器的边框),其它的根据需要自己修改一下样式即可. 2.组件封装 组件的封装用到了CSS动画.定位.,以及Element UI提供的下拉菜单组件el-dropdown.代码如下, <template> <div class="all" @click="clickFire&qu

  • Vue+Element UI 实现视频上传功能

    一.前言 项目中需要提供一个视频介绍,使用户能够快速.方便的了解如何使用产品以及注意事项. 前台使用Vue+Element UI中的el-upload组件实现视频上传及进度条展示,后台提供视频上传API并返回URL. 二.具体实现 1.效果图展示 2.HTML代码 <div class="album albumvideo"> <div> <p class="type_title"> <span>视频介绍</spa

随机推荐