吐了啊!产品要求树形多选组件支持单选,同时还要能全选

在树形组件显示复选框的情况下,check-strictly遵循父子不互相关联,通过在非叶子节点插槽增加按钮实现全选功能,从而实现树形组件单选情况下增加了全选功能。

## 实现效果

[demo](https://ztrainwilliams.github.io/formula-rule-editor/#/select-tree)

## 需求前情
在树形组件支持的原有模式下,要么是遵循父子互相关联,则无法单选一个非叶子节点(父级);要么无法遵循父子不互相关联,此模式下便是单选模式,当遇到大量选择的时候,需要逐个选择则无法满足快捷使用。当前的组件原有设计并没有完美的兼容模式,但是业务提出了这个需求,我们只要思考解决方案。

## 方案确认
1. 确认单选模式,开启check-strictly
2. 增加一个可全选的入口
3. 全选情况下可反选

## 代码实现
全选、反选实现
``` vue
<template>
  <el-tree-v2
    ref="treeV2Ref"
    v-loading="loading"
    :data="treeData"
    :props="props.props"
    :check-strictly="props.checkStrictly"
    :showCheckbox="props.showCheckbox"
    @check-change="treeChange"
  >
    <template #default="{ node, data }">
      <span class="prefix" :class="{ 'is-leaf': node.isLeaf }">
        <el-button
          v-if="data.children && data.children.length"
          link
          type="primary"
          @click.stop="nodeClick(node, data)"
          :disabled="node.disabled"
        >
          <slot name="select-all-title">
            [全选]
          </slot>
        </el-button>
        {{ node.label }}
      </span>
    </template>
  </el-tree-v2>
</template>

<script setup>
import { uniq, without } from 'lodash-es';

// 获取全部子节点
/**
 * @description: 
 * @param {Array} list
 * @param {Array} result
 * @return {Array}
 */
const getDeepChildren = (list, result = []) => {
  list.forEach((item) => {
    if (item.children && item.children.length > 0) {
      getDeepChildren(item.children, result);
    }
    !item.disabled && result.push(item.key);
  });
  return result;
};

/**
 * @description: 判断存在未勾选
 * @param {Array} checkedKeys
 * @param {Array} childrens
 * @return {Boolean}
 */
const isCheckAllChildren = (checkedKeys, childrens) => {
  const setCheckedKeys = new Set();
  checkedKeys.forEach((v) => setCheckedKeys.add(v));
  for (let i = 0; i < childrens.length; i += 1) {
    if (!setCheckedKeys.has(childrens[i])) {
      return false;
    }
  }
  return true;
};
/**
 * @description: 全选点击
 * @param {*} node
 * @return {*}
 */
const nodeClick = (node) => {
  if (node.disabled) return false;
  const checkedKeys = treeV2Ref.value?.getCheckedKeys();
  const childrens = [...getDeepChildren(node.children ?? []), node.key]; // 全选-包含本级
  nextTick(() => {
    let list = [];
    if (isCheckAllChildren(checkedKeys, childrens)) {
      // 反选
      list = without(checkedKeys, ...childrens);
      treeV2Ref.value.setCheckedKeys();
    } else {
      list = uniq([...checkedKeys, ...childrens]);
    }
    treeV2Ref.value.setCheckedKeys(list);
    update(list);
  });
};
</script>
```

## END
如果你有更好的建议和解决方案,可以多多探讨。

[组件treeV2](https://github.com/ZTrainWilliams/formula-rule-editor/tree/master/src/components/treeV2/index.vue)

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值