Vue 封装 多选级联组件 支持全选功能
- 使用方式和elm官方一致,原参数一致
- 主要参数:
- options:级联数菜单。多维数组
- mulSelectedVal:绑定值。id集合。且取值最后一层id
- collapseTags:是否tag展示
- fieldNames:自定义结构字段名。key-value
组件展示
数据提交展示;
使用方式
<el-form-item label="城市: ">
<multiple-cascader
:mul-selected-val.sync="searchFormData.areaIds"
:options="areaList" />
</el-form-item>
组件源码
<template>
<el-cascader
ref="elCascaderRef"
v-model="cascaderIds"
:show-all-levels="false"
:options="cascaderOptions"
:props="{ multiple: true, ...fieldNames }"
:collapse-tags="collapseTags"
clearable filterable
@change="onCascaderChange">
</el-cascader>
</template>
<script>
// 缓存值 上一次选中值
let lastSelected = []
let dataLevel = 0 // 级联层级, 默认0层
export default {
inheritAttrs: false,
name: 'multiple-cascader',
props: {
// 选项
options: {
type: Array,
default() {
return [];
}
},
// 已选中选项
mulSelectedVal: {
type: Array,
default() {
return [];
}
},
collapseTags: {
type: Boolean,
default: true
},
// 自定义字段名
fieldNames: {
type: Object,
default() {
return {
label: 'name',
value: 'id',
};
}
}
},
data() {
return {
cascaderIds: []
};
},
computed: {
// 级联列表
cascaderOptions() {
this.options.unshift({ children: null, id: '全选', name: '全选' })
return this.options
},
// 全选值
cascaderAllValue() {
var model = []
function tree2arr(arr, str, level) {
dataLevel = (level + 1) // 实际数据结构是几层
arr.forEach(it => {
let newStr = str.length ? [...str, it.id] : [it.id];
if (it.children) {
tree2arr(it.children, newStr, level + 1)
} else {
model.push(newStr)
}
})
}
tree2arr(this.cascaderOptions, [], 0)
return model
},
},
methods: {
onCascaderChange(node) {
let current = []; // 当前勾选项
let isCheck = false // 【勾选 | 反选】
if(node.length >= lastSelected.length) {
let keys = lastSelected.map(item => JSON.stringify(item))
current = node.filter(item => !keys.includes(JSON.stringify(item)))
isCheck = true
}else {
let keys = node.map(item => JSON.stringify(item))
current = lastSelected.filter(item => !keys.includes(JSON.stringify(item)))
isCheck = false
}
const currentValue = current.length > 0 ? current[0][0] || '' : ''
if (currentValue === '全选') {
if (isCheck) {
this.$set(this, 'cascaderIds', this.cascaderAllValue)
} else {
this.$set(this, 'cascaderIds', [])
}
} else {
// 除全选外
let areaListAll = JSON.parse(JSON.stringify(this.cascaderAllValue))
let firstValue = node.length > 0 ? node[0][0] || '' : ''
if (firstValue !== '全选') { areaListAll.shift(); }
if (node.length === areaListAll.length) {
this.$set(this, 'cascaderIds', [['全选'], ...this.cascaderIds])
} else {
// 选中了全部,然后取消了某一个
if (firstValue === '全选') {
const ab = node.filter((item, index) => index >= 1)
this.$set(this, 'cascaderIds', ab)
}
}
}
lastSelected = this.cascaderIds
this.$nextTick(() => {
let checkValue = this.$refs.elCascaderRef.getCheckedNodes() || []
console.log('最深层级:', checkValue);
// 更新绑定 筛选最后一层数据值
this.$emit('update:mulSelectedVal', checkValue.filter(item => item.level === dataLevel).map(item => item.value));
this.$emit('change', node)
})
},
}
};
</script>
<style scoped lang="scss">
</style>