element虽然功能很强大,也很方便,但是在实际开发中还是有很多不足,比方说下拉框多选时没有全选功能,这里的下拉框包含el-select和el-cascader级联选择器。这里我们都来封装一个组件,弥补下这个不足。
这里组件我们采用的是vue2.0,来看下代码实现:

<template>
  <el-cascader
    ref="cascaderEle"
    :options="optionList"
    :props="config"
    collapse-tags
    :filterable="filterable"
    :size="size"
    :style="{width: width + 'px'}"
    v-model="choiceEle"
    @change="selectChange"
    clearable>
  </el-cascader>
</template>

<script>
/**
 * options [{ value: "", label: "", childList: []}]
 * checkStrictly 设置父子节点取消选中关联
 * 获取选中结果 change事件
 * all 是全部
 * size 大小
 * filterable 是否支持筛选
  */
export default {
  name: 'AiCascaderAll',
  props: {
    options: {
      type: Array,
      default: () => {
        return [];
      }
    },
    width: {
      type: Number,
      default: 180
    },
    checkStrictly: {
      type: Boolean,
      default: false
    },
    filterable: {
      type: Boolean,
      default: true
    },
    size: {
      type: String,
      default: "mini"
    }
  },
  data() {
    return {
      optionList: [],
      lastSelectedList: [],
      choiceEle: [],
      allLength: 0,
      allOptions: [{ value: "all", label: "全部", childList: null }],
      config: {
        multiple: true,
        checkStrictly: false
      }
    }
  },
  watch: {
    options() {
      this.setData();
    }
  },
  mounted() {
    this.setData();
    this.config.checkStrictly = this.checkStrictly;
  },
  methods: {
    setData() {
      this.optionList = [];
      this.optionList = this.allOptions.concat(this.options);
      this.loopSelectData(this.optionList);
      // 记录下全部选中时的个数
      this.allLength = this.choiceEle.length;
      this.lastSelectedList = [...this.choiceEle];
      this.sendInfo();
    },
    selectChange(val) {
      let lastHasAll = this.lastSelectedList.find(arr => {
        return arr[0] === 'all';
      });
      let nowHasAll = val.find(arr => {
        return arr[0] === 'all';
      });
      if (lastHasAll && !nowHasAll) {
        // 点击取消了 全选
        // this.clearCascader();
        this.choiceEle = [];
        this.lastSelectedList = [];
        this.$nextTick(() => {
          this.sendInfo();
        });
        return;
      }
      if (!lastHasAll && nowHasAll) {
        this.choiceEle = [];
        // 点击了 全选
        this.loopSelectData(this.optionList);
        this.lastSelectedList = [...this.choiceEle];
        this.$nextTick(() => {
          this.sendInfo();
        });
        return;
      }
      // 当点选了除全部按钮外的所有 选中全部按钮
      if (!nowHasAll && val.length === this.allLength - 1) {
        this.choiceEle = [['all']].concat(this.choiceEle);
        val = [['all']].concat(val);
      }
      // 当全部选项都选中 这时取消了除全部按钮外的一个 去掉选中全部按钮
      if (nowHasAll && val.length < this.allLength) {
        val = val.filter(arr => {
          return arr[0] !== 'all';
        });
        this.choiceEle = [...val];
      }
      this.sendInfo();
      this.lastSelectedList = [...val];
    },
    loopSelectData(list, parentNode = []) {
      list.length > 0 &&
      list.forEach((e) => {
        let pNode = [...parentNode]; // 注意这里必须是深拷贝,否则会由于引用类型赋值的是地址(指针),导致parentNode在pNode更新时,同时被更新
        if (e.children && e.children.length > 0) {
          pNode.push(e.value);
          // 当没有关联时 需要每一级都存下
          if (this.checkStrictly) {
            this.choiceEle.push([...pNode]);
          }
          this.loopSelectData(e.children, pNode);
        } else {
          if (parentNode.length > 0) {
            this.choiceEle.push([...parentNode, e.value]);
          } else {
            this.choiceEle.push([e.value]);
          }
        }
      });
    },
    sendInfo() {
      this.$emit('change', this.choiceEle);
    }
  }
};
</script>

<style scoped></style>

这个代码干货满满,大家直接复制到项目中即可,使用时:

<ai-cascader-all
 :options="options"
  @change="cascaderChangeFun"
  :width="200"
/>

let options = [
{
    value: "zhinan",
    label: "指南",
    children: [
      {
        value: "shejiyuanze",
        label: "设计原则",
        children: [
          {
            value: "yizhi",
            label: "一致",
          },
          {
            value: "fankui",
            label: "反馈",
          }
        ]
      },
      {
        value: "daohang",
        label: "导航",
        children: [
          {
            value: "cexiangdaohang",
            label: "侧向导航",
          },
          {
            value: "dingbudaohang",
            label: "顶部导航",
          }
        ]
      }
    ]
  },
  {
    value: "ziyuan",
    label: "资源",
    children: [
      {
        value: "axure",
        label: "Axure Components",
      },
      {
        value: "sketch",
        label: "Sketch Templates",
      },
      {
        value: "jiaohu",
        label: "组件交互文档",
      },
    ],
  }
]

代码逻辑都有注释,有帮助到大家的话,点个赞不过分吧!

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐