根据博主vue+elementUI(el-cascader)实现全选功能_el-cascader全选_szjSmiling的博客-优快云博客的代码,修改为标准的后端返回格式
<template>
<div>
<el-cascader
v-model="selected"
clearable
filterable
:options="userOption"
:props="{
multiple: true,
value: 'value',
label: 'label',
}"
:collapse-tags="true"
placeholder="请选择"
@change="selectHandle"
>
<template #default="{ node, data }">
<span>{{ data.label }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</div>
</template>
<script setup>
import { ref } from 'vue'
const preSelected = ref([]) // 上次选中的数据
const originData = ref([]) // 源数据平铺成一级节点
const defaultExpandedKeys = ref([])
const selected = ref([])
const userOption = ref([
{ label: '全选', value: '全选' },
{ label: '层级0', value: '0' },
{
label: '层级1',
value: '1',
children: [
{
label: '层级11',
value: '11',
children: [
{ label: '层级111', value: '111' },
{ label: '层级112', value: '112' },
],
},
{
label: '层级12',
value: '12',
children: [{ label: '层级121', value: '121' }],
},
],
},
{
label: '层级2',
value: '2',
children: [
{ label: '层级21', value: '21' },
{ label: '层级22', value: '22' },
],
},
{
label: '层级3',
value: '3',
children: [{ label: '层级31', value: '31' }],
},
])
const defaultSelectSomeone = () => {
preSelected.value = []
selected.value = []
selected.value = [['2', '21']]
}
const defaultSelectAll = () => {
preSelected.value = []
selected.value = []
if (userOption.value[0].label !== '全选') {
userOption.value.unshift({ label: '全选', value: '全选' })
}
selectHandle([['全选']])
}
const judgetAllSelected = (node) => {
let isAllSelected = false
for (let i = 0; i < node.length; i++) {
if (node[i][0] === '全选') {
isAllSelected = true
break
}
}
return isAllSelected
}
const loopFlatData = (list, parentNode = []) => {
list.length > 0 &&
list.forEach((e) => {
let pNode = [...parentNode]
if (e.children && e.children.length > 0) {
pNode.push(e.value)
loopFlatData(e.children, pNode)
} else {
if (e.label !== '全选') {
if (parentNode.length > 0) {
pNode.push(e.value)
originData.value.push({ ...e, parentNode: pNode })
} else {
originData.value.push(e)
}
}
}
})
}
const loopSelectData = (list, parentNode = []) => {
list.length > 0 &&
list.forEach((e) => {
let pNode = [...parentNode]
if (e.children && e.children.length > 0) {
pNode.push(e.value)
loopSelectData(e.children, pNode)
} else {
if (parentNode.length > 0) {
selected.value.push([...parentNode, e.value])
} else {
selected.value.push([e.value])
}
}
})
}
const checkIsAddAllSelected = () => {
let list = userOption.value
if (originData.value.length === 0) {
loopFlatData(list)
}
let origin = originData.value
let now = [...selected.value].filter((item) => item[0] !== '全选')
if (origin.length > now.length) {
selected.value = selected.value.filter((item) => item[0] !== '全选')
} else {
if (selected.value[0] && selected.value[0][0] !== '全选') {
selected.value = [['全选'], ...selected.value]
}
}
}
const selectHandle = async (node) => {
defaultExpandedKeys.value = []
selected.value = []
let list = userOption.value
let current = []
if (node.length >= preSelected.value.length) {
let keys = preSelected.value.map((item) => JSON.stringify(item))
current = node.filter((item) => !keys.includes(JSON.stringify(item)))
console.log('选中某项', current)
} else {
let keys = node.map((item) => JSON.stringify(item))
current = preSelected.value.filter(
(item) => !keys.includes(JSON.stringify(item))
)
console.log('取消选中', current)
defaultExpandedKeys.value = current[0]
}
const currentValue = current.length > 0 ? current[0][0] || '' : ''
if (currentValue === '全选') {
if (judgetAllSelected(node)) {
loopSelectData(list)
} else {
selected.value = []
}
} else {
selected.value = node
}
checkIsAddAllSelected()
preSelected.value = selected.value
changeHandle()
}
const changeHandle = () => {
console.log('changeHandle: ', selected.value)
}
</script>