(element-plus cascader级联组件 父子半关联(父取消子不取消 子全选自动勾选父))

(element-plus cascader级联组件 父子半关联(父取消子不取消 子全选自动勾选父))

需求

1、分类项,标签项,不可以勾选,标签值可以勾选; 2、当标签值下还有标签值时下一级全勾选上父级标签值自动打勾,父级取消勾选,子标签值不取消勾选; 3、每一个标签值都是独立的标签。

思路

使用组件自带的父子关联肯定是做不了这个需求,所以需要设置checkStrictly属性设置为true,然后通过判断现有选中的子节点数据长度是否去勾选父 使用ref调用组件内部暴露的calculateCheckedValue更新视图 不可以勾选的选项通过在对应的数据位置设置disabled:true,再通过样式把前置复选框给隐藏就可以

效果图

代码

html 复制代码
<!-- html -->
<el-cascader
  :props="cascaderProps"
  :options="cascaderOptions"
  :show-all-levels="false"
  placeholder="请选择"
  collapse-tags
  collapse-tags-tooltip
  :max-collapse-tags="5"
  ref="cascaderRef"
  clearable
  v-model="opearteFrom.labelIds"
/>
typescript 复制代码
// 内容标签下拉值
const cascaderRef = ref()
const cascaderOptions = ref([])
const cascaderProps = { multiple: true, value: 'id', label: 'name', checkStrictly: true, emitPath: false }
const checkedNode = ref([])

watch(() => opearteFrom.value.labelIds, (newArr, oldArr) => {
  if (newArr && newArr.length) {
    const current = findCurrentCascaderChecked(newArr, oldArr || [])
    if (!current) return
    nextTick(() => {
      // 从级联选择器中取出内部的节点数组,找到当前节点
      let targetNode:any = ''
      checkedNode.value = cascaderRef.value.getCheckedNodes()
      targetNode = checkedNode.value.find((item:CascaderNode) => {
        return item.value === current.value
      })
      if (current.type === 'checked') {
        if (targetNode) {
          const peerIds = targetNode.parent.childrenData.map((obj:CascaderOption) => obj.id)
          const repeatCount = countMatchingIds(peerIds, opearteFrom.value.labelIds || [])
          if (repeatCount >= peerIds.length && !targetNode.parent.isDisabled) {
            targetNode.parent.checked = true
            cascaderRef.value.cascaderPanelRef.calculateCheckedValue()
          }
        }
      } else if (current.type === 'cancel') {
        if (targetNode) {
          targetNode.parent.checked = false
          cascaderRef.value.cascaderPanelRef.calculateCheckedValue()
        }
      }
    })
  }
}, { deep: true })


// 最后获取选中的值
const checkedNodeArr = cascaderRef.value.getCheckedNodes()
const labelIds = checkedNodeArr.map((obj:any) => parseInt(obj.value))
console.log(labelIds)
typescript 复制代码
// utils.ts 
// 判断当前操作是选中还是取消
export const findCurrentCascaderChecked = (newArr: number[], oldArr: number[]) => {
  const catchNewArr = [...newArr]
  const catchOldArr = [...oldArr]
  if (catchNewArr.length > catchOldArr.length) {
    for (let i = 0; i < catchNewArr.length; i++) {
      const targetIndex = catchOldArr.indexOf(catchNewArr[i])
      if (targetIndex === -1) {
        return {
          value: catchNewArr[i],
          type: 'checked'
        }
      }
    }
  } else {
    for (let i = 0; i < catchOldArr.length; i++) {
      const targetIndex = catchNewArr.indexOf(catchOldArr[i])
      if (targetIndex === -1) {
        return {
          value: catchOldArr[i],
          type: 'cancel'
        }
      }
    }
  }
}

// 两数字数组 重复值计数
export function countMatchingIds(arr1: number[], arr2: number[]) {
  // 创建一个Set集合,用于存储数组1中的所有ID
  const idSet = new Set(arr1)
  let count = 0

  // 遍历数组2,检查是否存在于Set集合中,并增加计数
  for (let i = 0; i < arr2.length; i++) {
    if (idSet.has(arr2[i])) {
      count++
    }
  }
  return count
}

拓展

到这产品描述的需求就做完,思考了一下,感觉很别扭,不太合理。正常逻辑应该是除开不可勾选的,标签值父子关联,也就是父勾选子自动勾选,这里提供两个方法进行参考

typescript 复制代码
// 处理树节点 选中父 子全部选上
export function checkedChildren(val) {
  for (const item of val) {
    item.checked = true
    if (item.children && item.children.length !== 0) {
      checkedChildren(item.children)
    }
  }
  return val
}

// 处理树节点 取消父 子全部取消
export function cancelChildren(val) {
  for (const item of val) {
    item.checked = false
    if (item.children && item.children.length !== 0) {
      cancelChildren(item.children)
    }
  }
  return val
}

// 传入的val 就是上面 findCurrentCascaderChecked方法返回的value

小声bb

产品a:我就要这么做,我感觉挺简单的。 我:市面上有这种吗,可以找到给我参考下吗? 产品b: emmm....别管,就是要这种,你就说会不会做吧。 我:...... 擦,真的是产品一句话说完就下班,开发裤裤加班改。。。。

相关推荐
清风细雨_林木木2 分钟前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo23 分钟前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
不灭锦鲤34 分钟前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名1 小时前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹1 小时前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
Maỿbe1 小时前
利用html制作简历网页和求职信息网页
前端·html
森叶1 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹2 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹2 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts
繁依Fanyi2 小时前
ColorAid —— 一个面向设计师的色盲模拟工具开发记
开发语言·前端·vue.js·编辑器·codebuddy首席试玩官