Skip to main content

Cascader 级联选择器

需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等。

从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。

比起 Select 组件,可以在同一个浮层中完成选择,有较好的体验。

引入​

import {Cascader} from 'acud';

基本用法​

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
disabled: true,
children: [
{
label: '选项三二一',
value: 'op3-2-1'
},
{
label: '选项三二二',
value: 'op3-2-2'
}
]
},
{
label: '选项三三',
value: 'op3-3',
children: [
{
label: '选项三三一',
value: 'op3-3-1',
children: [
{
label: '选项三三一一',
value: 'op3-3-1-1'
},
{
label: '选项三三一二',
value: 'op3-3-1-2',
disabled: true
}
]
}
]
},
{
label: '选项三四',
value: 'op3-4'
},
{
label: '选项三五',
value: 'op3-5'
},
{
label: '选项三六',
value: 'op3-6'
},
{
label: '选项三七',
value: 'op3-7'
},
{
label: '选项三八',
value: 'op3-8'
}
]
}
];

return (
<Cascader options={options} />
);
}

默认值​

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
children: [
{
label: '选项三二一',
value: 'op3-2-1'
}
]
},
{
label: '选项三三',
value: 'op3-3',
children: [
{
label: '选项三三一',
value: 'op3-3-1',
children: [
{
label: '选项三三一一',
value: 'op3-3-1-1',
children: []
}
]
}
]
},
{
label: '选项三四',
value: 'op3-4'
},
{
label: '选项三五',
value: 'op3-5'
},
{
label: '选项三六',
value: 'op3-6'
},
{
label: '选项三七',
value: 'op3-7'
},
{
label: '选项三八',
value: 'op3-8'
},
{
label: '选项三九',
value: 'op3-9'
}
]
}
];

const MAX_LEVEL = 5;
const MAX_NUM = 9;
const NUMBER_MAP = ['一', '二', '三', '四', '五', '六', '七', '八', '九'];

const auto = (level = 1, suffix = '') => {
const res = [];
for (let i = 0; i < MAX_NUM; i++) {
const current = {
label: `选项${suffix}${NUMBER_MAP[i]}`,
value: `op${suffix}${NUMBER_MAP[i]}`,
children: level < MAX_LEVEL
? auto(level + 1, `${suffix}${NUMBER_MAP[i]}`)
: undefined
};
res.push(current);
}
return res;
};

const autoOptions = auto();
const defaultValue = ['op3', 'op3-3', 'op3-3-1', 'op3-3-1-1'];
const defaultValue2 = ['op三', 'op三一', 'op三一二', 'op三一二一', 'op三一二一一'];

return (
<div className="acux-demo-column">
<Cascader options={options} allowClear showSearch defaultValue={defaultValue} />
<Cascader
options={autoOptions}
allowClear
showSearch
defaultValue={defaultValue2}
/>
</div>
);
}

不同位置​

设置浮层预设位置

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
disabled: true,
children: [
{
label: '选项三二一',
value: 'op3-2-1'
},
{
label: '选项三二二',
value: 'op3-2-2'
}
]
},
{
label: '选项三三',
value: 'op3-3',
children: [
{
label: '选项三三一',
value: 'op3-3-1',
children: [
{
label: '选项三三一一',
value: 'op3-3-1-1'
},
{
label: '选项三三一二',
value: 'op3-3-1-2',
disabled: true
}
]
}
]
},
{
label: '选项三四',
value: 'op3-4'
},
{
label: '选项三五',
value: 'op3-5'
},
{
label: '选项三六',
value: 'op3-6'
},
{
label: '选项三七',
value: 'op3-7'
},
{
label: '选项三八',
value: 'op3-8'
}
]
}
];

return (
<Cascader options={options} popupPlacement="topLeft" />
);
}

级联多选​

function App() {
const defaultOptions = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1',
isLeaf: false
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
disabled: true,
children: [
{
label: '选项三二一',
value: 'op3-2-1'
},
{
label: '选项三二二',
value: 'op3-2-2'
}
]
},
{
label: '选项三三',
value: 'op3-3',
children: [
{
label: '选项三三一',
value: 'op3-3-1',
children: [
{
label: '选项三三一一',
value: 'op3-3-1-1'
},
{
label: '选项三三一二',
value: 'op3-3-1-2',
disabled: true
}
]
}
]
},
{
label: '选项三四',
value: 'op3-4'
},
{
label: '选项三五',
value: 'op3-5'
},
{
label: '选项三六',
value: 'op3-6'
},
{
label: '选项三七',
value: 'op3-7'
},
{
label: '选项三八',
value: 'op3-8'
}
]
},
{
label: '选项四',
value: 'op4',
children: [
{
label: '选项四一',
value: 'op4-1',
disabled: true
}
]
}
];

const [options, setOptions] = useState(defaultOptions);

const loadData = selectedOptions => {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;

// load options lazily
setTimeout(() => {
targetOption.loading = false;
targetOption.children = [
{
label: `${targetOption.label}-1`,
value: `${targetOption.value}-1`
},
{
label: `${targetOption.label}-2`,
value: `${targetOption.value}-2`
}
];
setOptions([...options]);
}, 1000);
};

return (
<Cascader
options={options}
mode="multiple"
showSearch
maxTagTextLength={7}
loadData={loadData}
onChange={(value, options) => console.log(value, options)}
/>
);
}

限制 Tag 数量​

设置最多显示多少个 Tag,只适用于多选场景。

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
disabled: true,
children: [
{
label: '选项三二一',
value: 'op3-2-1'
},
{
label: '选项三二二',
value: 'op3-2-2'
}
]
},
{
label: '选项三三',
value: 'op3-3',
children: [
{
label: '选项三三一',
value: 'op3-3-1',
children: [
{
label: '选项三三一一',
value: 'op3-3-1-1'
},
{
label: '选项三三一二',
value: 'op3-3-1-2',
disabled: true
}
]
}
]
},
{
label: '选项三四',
value: 'op3-4'
},
{
label: '选项三五',
value: 'op3-5'
},
{
label: '选项三六',
value: 'op3-6'
},
{
label: '选项三七',
value: 'op3-7'
},
{
label: '选项三八',
value: 'op3-8'
}
]
}
];

const defaultValue = [['op3', 'op3-1'], ['op3', 'op3-4'], ['op3', 'op3-5'], ['op3', 'op3-6']];

return (
<Cascader
options={options}
mode="multiple"
showSearch
defaultValue={defaultValue}
maxTagCount={2}
onChange={(value, options) => console.log(value, options)}
/>
);
}

禁用状态​

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
disabled: true,
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1',
disabled: true
},
{
label: '选项三二',
value: 'op3-2',
children: [
{
label: '选项三二一',
value: 'op3-2-1'
}
]
}
]
}
];

const defaultValue = ['op3', 'op3-2', 'op3-2-1'];

return (
<div className="acux-demo-column">
<Cascader options={options} disabled />
<Cascader options={options} disabled defaultValue={defaultValue} />
<Cascader mode="multiple" options={options} disabled defaultValue={[defaultValue]} />
</div>
);
}

支持搜索​

function App() {
const options = [
{
label: '选项一',
value: 'op1',
children: [
{
label: '选项一一',
value: 'op1-1',
children: [
{
label: '选项一一一',
value: 'op1-1-1'
}
]
},
{
label: '选项一二',
value: 'op1-2'
}
]
},
{
label: '选项二',
value: 'op2',
children: [
{
label: '选项二一',
value: 'op2-1',
children: [
{
label: '选项二一一',
value: 'op2-1-1'
}
]
}
]
},
{
label: '选项三',
value: 'op3',
children: [
{
label: '选项三一',
value: 'op3-1'
},
{
label: '选项三二',
value: 'op3-2',
children: [
{
label: '选项三二一',
value: 'op3-2-1'
},
{
label: '选项三二二',
value: 'op3-2-2'
}
]
}
]
}
];

return (
<Cascader options={options} showSearch />
);
}

动态加载​

使用 loadData 实现动态加载选项。

注意

loadData 与 showSearch 无法一起使用。

function App() {
const defaultOptions = [
{
value: 'op1',
label: '选项一',
isLeaf: false,
loading: true
},
{
value: 'op2',
label: '选项二',
isLeaf: false
}
];

const [options, setOptions] = useState(defaultOptions);

const loadData = selectedOptions => {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;

// load options lazily
setTimeout(() => {
targetOption.loading = false;
targetOption.children = [
{
label: `${targetOption.label}一`,
value: `${targetOption.value}-1`
},
{
label: `${targetOption.label}二`,
value: `${targetOption.value}-2`
}
];
setOptions([...options]);
}, 1000);
};

return (
<Cascader
options={options}
loadData={loadData}
/>
);
}

API​

参数说明类型默认值
allowClear是否支持清除booleantrue
autoFocus自动获取焦点booleanfalse
bordered是否有边框booleantrue
changeOnSelect当此项为 true 时,点选每级菜单选项值都会发生变化,具体见上面的演示booleanfalse
className自定义类名string--
defaultValue默认的选中项string[]〡number[][]
disabled禁用booleanfalse
displayRender选择后展示的渲染函数(label, selectedOptions) => ReactNodelabel => label.join('/')
dropdownRender自定义下拉框内容(menus: ReactNode) => ReactNode--
expandIcon自定义次级菜单展开图标ReactNode--
fieldNames自定义 options 中 label name children 的字段object{ label: 'label', value: 'value', children: 'children' }
getPopupContainer菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。function(triggerNode)() => document.body
loadData用于动态加载选项,无法与 showSearch 一起使用(selectedOptions) => void--
maxTagTextLength最大显示的 tag 文本长度,仅 多选 时有效number8
mode设置 Cascader 的模式为多选'multiple'undefined
notFoundContent当下拉列表为空时显示的内容stringNot Found
options可选项数据源Option[]--
placeholder输入框占位文本string'请选择'
popupClassName自定义浮层类名string--
popupPlacement浮层预设位置:bottomLeft bottomRight topLeft topRightstringbottomLeft
popupVisible控制浮层显隐boolean--
showSearch在选择框中显示搜索框boolean〡Objectfalse
style自定义样式CSSProperties--
suffixIcon自定义的选择框后缀图标ReactNode--
value指定选中项string[]〡number[]--
onChange选择完成后的回调(value, selectedOptions) => void--
onClear清空内容时的回调() => void--
onPopupVisibleChange显示/隐藏浮层的回调(value) => void--

showSearch​

showSearch 为对象时,其中的字段:

参数说明类型默认值
limit搜索结果展示数量number〡false50
filter接收 inputValue path 两个参数,当 path 符合筛选条件时,应返回 true,反之则返回 falsefunction(inputValue, path): boolean--
matchInputWidth搜索结果列表是否与输入框同宽booleantrue
render用于渲染 filter 后的选项function(inputValue, path): ReactNode--
sort用于排序 filter 后的选项function(a, b, inputValue)--

Option​

interface Option {
value: string | number;
label?: React.ReactNode;
disabled?: boolean;
children?: Option[];
isLeaf?: boolean;
}

方法​

名称描述
blur()移除焦点
focus()获取焦点