# ByCascaderPanel 级联面板选择器
基于 Element UI 的 el-cascader-panel
组件封装的级联面板选择器,支持单选/多选模式、搜索功能、聚合模式、禁用状态等功能。提供左右分栏的交互界面,左侧显示可选项目,右侧显示已选项。
# 基础用法
<template>
<ByCascaderPanel v-model="selectedValues" :options="options" :panel-height="300" @change="handleChange" />
</template>
<script>
export default {
data() {
return {
selectedValues: ['lisi', 'zhaoliu'],
options: [
{
label: '技术部',
value: 'tech',
children: [
{
label: '前端组',
value: 'frontend',
children: [
{ label: '张三', value: 'zhangsan' },
{ label: '李四', value: 'lisi' },
{ label: '王五', value: 'wangwu' }
]
},
{
label: '后端组',
value: 'backend',
children: [
{ label: '赵六', value: 'zhaoliu' },
{ label: '钱七', value: 'qianqi' }
]
}
]
},
{
label: '产品部',
value: 'product',
children: [
{
label: '产品组',
value: 'product_group',
children: [
{ label: '孙八', value: 'sunba' },
{ label: '周九', value: 'zhoujiu' }
]
}
]
}
]
}
},
methods: {
handleChange(data) {
console.log('选择变化:', data)
}
}
}
</script>
# 单选模式
<template>
<ByCascaderPanel
v-model="selectedValue"
:options="options"
:cascader-props="singleProps"
:panel-height="200"
search-placeholder="请输入部门或人员名称"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValue: 'zhengchenggong', // 单选模式,使用单个值
options: [
{
name: '明朝',
id: 'ming_dynasty',
children: [
{
name: '明朝·武将集团',
id: 'ming_military_officials',
children: [
{ name: '戚继光', id: 'qijiguang', status: 1 },
{ name: '郑成功', id: 'zhengchenggong', status: 1 }
]
}
]
}
],
singleProps: {
multiple: false,
label: 'name',
value: 'id',
children: 'children'
}
}
}
}
</script>
# 多选模式
<template>
<ByCascaderPanel
v-model="selectedValues"
:options="options"
:cascader-props="multipleProps"
:panel-height="250"
search-placeholder="请输入部门或人员名称"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValues: ['baijuyi', 'zhengchenggong'],
multipleProps: {
multiple: true,
label: 'name',
value: 'id',
children: 'children'
}
}
}
}
</script>
# 聚合模式
聚合模式:当父项的所有子项都被选中时,只返回父项ID,不包含子项。
<template>
<ByCascaderPanel
v-model="selectedValues"
:options="options"
:cascader-props="multipleProps"
:aggregation-mode="true"
:parent-node-prefix="'__parent__'"
:panel-height="300"
search-placeholder="请输入朝代或人物名称"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValues: ['baijuyi', 'zhengchenggong'],
options: [
{
name: '唐朝',
id: 'tang_dynasty',
children: [
{
name: '唐朝·文官集团',
id: 'tang_civil_officials',
children: [
{ name: '李白', id: 'libai' },
{ name: '杜甫', id: 'dufu' },
{ name: '白居易', id: 'baijuyi' }
]
}
]
}
],
multipleProps: {
multiple: true,
label: 'name',
value: 'id',
children: 'children'
}
}
},
methods: {
handleChange(data) {
console.log('聚合模式选择变化:', data)
// 当选择"部门"下的所有子项时,聚合模式会只返回"部门"的ID,而不是所有子项ID
}
}
}
</script>
# 聚合模式说明
- parentNodePrefix: 非叶子节点前缀标识,用于区分叶子节点和非叶子节点
- 在聚合模式下,如果子项全部选中,会直接返回父项ID
- 支持复杂的层级结构聚合,减少返回数据量
# parentNodePrefix 使用示例
<template>
<ByCascaderPanel
v-model="selectedValues"
:options="options"
:cascader-props="multipleProps"
:aggregation-mode="true"
:parent-node-prefix="'__parent__'"
:panel-height="300"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValues: ['__parent__department1', 'employee1', 'employee2'],
options: [
{
name: '技术部',
id: 'department1', // 非叶子节点,在聚合模式下需要添加前缀
children: [
{ name: '张三', id: 'employee1' },
{ name: '李四', id: 'employee2' }
]
}
],
multipleProps: {
multiple: true,
label: 'name',
value: 'id',
children: 'children'
}
}
},
methods: {
handleChange(data) {
console.log('聚合模式选择变化:', data)
// 当选择技术部下的所有员工时,会返回 '__parent__department1'
// 当只选择部分员工时,会返回具体的员工ID数组
}
}
}
</script>
# 禁用状态配置
<template>
<ByCascaderPanel
v-model="selectedValues"
:options="options"
disabled-field="status"
:disabled-value="0"
:panel-height="300"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValues: [],
options: [
{
name: '唐朝',
id: 'tang_dynasty',
children: [
{
name: '唐朝·文官集团',
id: 'civil_officials',
children: [
{ name: '李白', id: 'libai', status: 1 }, // 启用
{ name: '杜甫', id: 'dufu', status: 0 }, // 禁用
{ name: '白居易', id: 'baijuyi', status: 1 } // 启用
]
}
]
}
]
}
}
}
</script>
# 自定义禁用判断函数
<template>
<ByCascaderPanel
v-model="selectedValues"
:options="options"
:disabled-check="customDisabledCheck"
:panel-height="300"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedValues: [],
options: [
{
name: '技术部',
id: 'tech',
children: [
{
name: '前端组',
id: 'frontend',
children: [
{ name: '张三', id: 'zhangsan', role: 'admin' },
{ name: '李四', id: 'lisi', role: 'user' },
{ name: '王五', id: 'wangwu', role: 'guest' }
]
}
]
}
]
}
},
methods: {
customDisabledCheck(item) {
// 自定义禁用逻辑:只有 role 为 'user' 的项才能选择
return item.role !== 'user'
}
}
}
</script>
# 方法调用示例
<template>
<div>
<div class="button-group">
<el-button @click="clearSelection">清空选择</el-button>
<el-button @click="setDefaultSelection">设置默认选择</el-button>
<el-button @click="getSelectedData">获取选择数据</el-button>
</div>
<ByCascaderPanel ref="cascaderPanel" v-model="selectedValues" :options="options" @change="handleChange" />
</div>
</template>
<script>
export default {
data() {
return {
selectedValues: [],
options: [
// ... 选项数据
]
}
},
methods: {
clearSelection() {
this.$refs.cascaderPanel.clearSelection()
},
setDefaultSelection() {
this.$refs.cascaderPanel.setValue([
['tech', 'frontend', 'zhangsan'],
['product', 'product_group', 'sunba']
])
},
getSelectedData() {
const data = this.$refs.cascaderPanel.getSelectedData()
this.$message.success(`已选择 ${data.count} 项`)
console.log('选择数据:', data)
}
}
}
</script>
# API
# Props
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
value / v-model | 已选值 | Array / Number / String | [] |
options | 级联数据源 | Array | [] |
cascaderProps | 级联面板配置 | Object | { multiple: true, label: 'label', value: 'value', children: 'children' } |
panelHeight | 面板高度(px) | Number / String | 300 |
searchPlaceholder | 搜索占位符 | String | '请输入名称搜索' |
disabledField | 禁用字段名(只针对叶子节点) | String | 'disabled' |
disabledValue | 禁用值(只针对叶子节点) | String / Number / Boolean | true |
disabledCheck | 自定义禁用判断函数 | Function | null |
showSelectAll | 是否显示全选按钮 | Boolean | true |
aggregationMode | 是否聚合模式 | Boolean | false |
parentNodePrefix | 非叶子节点前缀标识(聚合模式下用于标识非叶子节点) | String | 'parent' |
# cascaderProps 配置
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
multiple | 是否多选 | Boolean | true |
label | 指定选项的标签为选项对象的某个属性值 | String | 'label' |
value | 指定选项的值为选项对象的某个属性值 | String | 'value' |
children | 指定选项的子选项为选项对象的某个属性值 | String | 'children' |
# Events
事件名 | 说明 | 参数 |
---|---|---|
change | 选择变化时触发 | data: { valuesPath: Array, values: Array/String, items: Array, count: Number } |
input | v-model 绑定值变化时触发 | value: Array/String |
# Methods
方法名 | 说明 | 参数 |
---|---|---|
setValue | 设置选择值 | values: Array/String |
clearSelection | 清空选择 | - |
getSelectedData | 获取选中的数据 | - |
# getSelectedData 返回值
参数 | 说明 | 类型 |
---|---|---|
valuesPath | 路径数组(聚合模式下已聚合) | Array |
values | 外部value(单选时返回单个值,多选时返回数组) | Array/String |
items | 已选项列表 | Array |
count | 已选项数量 | Number |
# 数据格式
# 基础数据格式
const options = [
{
label: '技术部', // 显示文本
value: 'tech', // 选项值
disabled: false, // 是否禁用(可选)
children: [
// 子选项
{
label: '前端组',
value: 'frontend',
children: [
{ label: '张三', value: 'zhangsan' },
{ label: '李四', value: 'lisi' }
]
}
]
}
]
# 自定义字段数据格式
const options = [
{
name: '技术部', // 自定义显示字段
id: 'tech', // 自定义值字段
status: 1, // 自定义禁用字段
children: [
{
name: '前端组',
id: 'frontend',
status: 1,
children: [
{ name: '张三', id: 'zhangsan', status: 1 },
{ name: '李四', id: 'lisi', status: 0 } // status为0表示禁用
]
}
]
}
]
# 聚合模式数据格式
在聚合模式下,非叶子节点需要添加前缀标识以避免ID冲突:
const options = [
{
name: '技术部',
id: 'tech', // 非叶子节点,在聚合模式下需要添加前缀
children: [
{
name: '前端组',
id: 'frontend', // 非叶子节点,在聚合模式下需要添加前缀
children: [
{ name: '张三', id: 'zhangsan' }, // 叶子节点,不需要前缀
{ name: '李四', id: 'lisi' } // 叶子节点,不需要前缀
]
}
]
}
]
// 在聚合模式下,选择值可能包含前缀:
const selectedValues = [
'__parent__tech', // 表示选择了整个技术部
'__parent__frontend', // 表示选择了整个前端组
'zhangsan', // 表示只选择了张三
'lisi' // 表示只选择了李四
]
# 功能特性
# 1. 搜索功能
- 支持按名称搜索,实时过滤选项
- 搜索结果会展开所有匹配的路径
- 搜索模式下支持选择操作
- 搜索无结果时显示空状态
# 2. 全选功能
- 多选模式下支持全选/取消全选
- 聚合模式下智能判断是否全选
- 全选时只选择所有可选的叶子节点
# 3. 聚合模式
- 当父项的所有子项都被选中时,只返回父项ID
- 减少返回数据量,优化性能
- 支持复杂的层级结构聚合
- 通过
parentNodePrefix
属性区分叶子节点和非叶子节点 - 在聚合模式下,非叶子节点需要添加前缀标识以避免ID冲突
# 4. 禁用状态
- 支持字段级别的禁用配置
- 支持自定义禁用判断函数
- 禁用项不可选择,但会显示在列表中