Cascader 级联选择

级联选择框。

何时使用

  • 需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等。
  • 从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。
  • 比起 Select 组件,可以在同一个浮层中完成选择,有较好的体验。

代码演示

Cascader 级联选择 - 图1

基本

省市区级联。

  1. <template>
  2. <a-cascader :options="options" @change="onChange" placeholder="Please select" />
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. options: [
  9. {
  10. value: 'zhejiang',
  11. label: 'Zhejiang',
  12. children: [
  13. {
  14. value: 'hangzhou',
  15. label: 'Hangzhou',
  16. children: [
  17. {
  18. value: 'xihu',
  19. label: 'West Lake',
  20. },
  21. ],
  22. },
  23. ],
  24. },
  25. {
  26. value: 'jiangsu',
  27. label: 'Jiangsu',
  28. children: [
  29. {
  30. value: 'nanjing',
  31. label: 'Nanjing',
  32. children: [
  33. {
  34. value: 'zhonghuamen',
  35. label: 'Zhong Hua Men',
  36. },
  37. ],
  38. },
  39. ],
  40. },
  41. ],
  42. };
  43. },
  44. methods: {
  45. onChange(value) {
  46. console.log(value);
  47. },
  48. },
  49. };
  50. </script>

Cascader 级联选择 - 图2

选择即改变

这种交互允许只选中父级选项。

  1. <template>
  2. <a-cascader :options="options" @change="onChange" changeOnSelect />
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. options: [
  9. {
  10. value: 'zhejiang',
  11. label: 'Zhejiang',
  12. children: [
  13. {
  14. value: 'hangzhou',
  15. label: 'Hangzhou',
  16. children: [
  17. {
  18. value: 'xihu',
  19. label: 'West Lake',
  20. },
  21. ],
  22. },
  23. ],
  24. },
  25. {
  26. value: 'jiangsu',
  27. label: 'Jiangsu',
  28. children: [
  29. {
  30. value: 'nanjing',
  31. label: 'Nanjing',
  32. children: [
  33. {
  34. value: 'zhonghuamen',
  35. label: 'Zhong Hua Men',
  36. },
  37. ],
  38. },
  39. ],
  40. },
  41. ],
  42. };
  43. },
  44. methods: {
  45. onChange(value) {
  46. console.log(value);
  47. },
  48. },
  49. };
  50. </script>

Cascader 级联选择 - 图3

自定义已选项

例如给最后一项加上邮编链接。

  1. <template>
  2. <a-cascader
  3. :options="options"
  4. :defaultValue="['zhejiang', 'hangzhou', 'xihu']"
  5. style="width: 100%"
  6. >
  7. <template slot="displayRender" slot-scope="{labels, selectedOptions}">
  8. <span v-for="(label, index) in labels" :key="selectedOptions[index].value">
  9. <span v-if="index === labels.length - 1">
  10. {{label}} (<a @click="e => handleAreaClick(e, label, selectedOptions[index])"
  11. >{{selectedOptions[index].code}}</a
  12. >)
  13. </span>
  14. <span v-else @click="onChange">
  15. {{label}} /
  16. </span>
  17. </span>
  18. </template>
  19. </a-cascader>
  20. </template>
  21. <script>
  22. export default {
  23. data() {
  24. return {
  25. options: [
  26. {
  27. value: 'zhejiang',
  28. label: 'Zhejiang',
  29. children: [
  30. {
  31. value: 'hangzhou',
  32. label: 'Hangzhou',
  33. children: [
  34. {
  35. value: 'xihu',
  36. label: 'West Lake',
  37. code: 752100,
  38. },
  39. ],
  40. },
  41. ],
  42. },
  43. {
  44. value: 'jiangsu',
  45. label: 'Jiangsu',
  46. children: [
  47. {
  48. value: 'nanjing',
  49. label: 'Nanjing',
  50. children: [
  51. {
  52. value: 'zhonghuamen',
  53. label: 'Zhong Hua Men',
  54. code: 453400,
  55. },
  56. ],
  57. },
  58. ],
  59. },
  60. ],
  61. };
  62. },
  63. methods: {
  64. onChange(value) {
  65. console.log(value);
  66. },
  67. handleAreaClick(e, label, option) {
  68. e.stopPropagation();
  69. console.log('clicked', label, option);
  70. },
  71. },
  72. };
  73. </script>

Cascader 级联选择 - 图4

可以自定义显示

切换按钮和结果分开。

  1. <template>
  2. <span>
  3. {{text}} &nbsp;
  4. <a-cascader :options="options" @change="onChange">
  5. <a href="#">Change city</a>
  6. </a-cascader>
  7. </span>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. text: 'Unselect',
  14. options: [
  15. {
  16. value: 'zhejiang',
  17. label: 'Zhejiang',
  18. children: [
  19. {
  20. value: 'hangzhou',
  21. label: 'Hangzhou',
  22. children: [
  23. {
  24. value: 'xihu',
  25. label: 'West Lake',
  26. },
  27. ],
  28. },
  29. ],
  30. },
  31. {
  32. value: 'jiangsu',
  33. label: 'Jiangsu',
  34. children: [
  35. {
  36. value: 'nanjing',
  37. label: 'Nanjing',
  38. children: [
  39. {
  40. value: 'zhonghuamen',
  41. label: 'Zhong Hua Men',
  42. },
  43. ],
  44. },
  45. ],
  46. },
  47. ],
  48. };
  49. },
  50. methods: {
  51. onChange(value, selectedOptions) {
  52. this.text = selectedOptions.map(o => o.label).join(', ');
  53. },
  54. },
  55. };
  56. </script>

Cascader 级联选择 - 图5

默认值

默认值通过数组的方式指定。

  1. <template>
  2. <a-cascader
  3. :options="options"
  4. @change="onChange"
  5. :defaultValue="['zhejiang', 'hangzhou', 'xihu']"
  6. />
  7. </template>
  8. <script>
  9. export default {
  10. data() {
  11. return {
  12. options: [
  13. {
  14. value: 'zhejiang',
  15. label: 'Zhejiang',
  16. children: [
  17. {
  18. value: 'hangzhou',
  19. label: 'Hangzhou',
  20. children: [
  21. {
  22. value: 'xihu',
  23. label: 'West Lake',
  24. },
  25. ],
  26. },
  27. ],
  28. },
  29. {
  30. value: 'jiangsu',
  31. label: 'Jiangsu',
  32. children: [
  33. {
  34. value: 'nanjing',
  35. label: 'Nanjing',
  36. children: [
  37. {
  38. value: 'zhonghuamen',
  39. label: 'Zhong Hua Men',
  40. },
  41. ],
  42. },
  43. ],
  44. },
  45. ],
  46. };
  47. },
  48. methods: {
  49. onChange(value) {
  50. console.log(value);
  51. },
  52. },
  53. };
  54. </script>

Cascader 级联选择 - 图6

禁用选项

通过指定 options 里的 disabled 字段。

  1. <template>
  2. <a-cascader :options="options" @change="onChange" />
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. options: [
  9. {
  10. value: 'zhejiang',
  11. label: 'Zhejiang',
  12. children: [
  13. {
  14. value: 'hangzhou',
  15. label: 'Hangzhou',
  16. children: [
  17. {
  18. value: 'xihu',
  19. label: 'West Lake',
  20. },
  21. ],
  22. },
  23. ],
  24. },
  25. {
  26. value: 'jiangsu',
  27. label: 'Jiangsu',
  28. disabled: true,
  29. children: [
  30. {
  31. value: 'nanjing',
  32. label: 'Nanjing',
  33. children: [
  34. {
  35. value: 'zhonghuamen',
  36. label: 'Zhong Hua Men',
  37. },
  38. ],
  39. },
  40. ],
  41. },
  42. ],
  43. };
  44. },
  45. methods: {
  46. onChange(value) {
  47. console.log(value);
  48. },
  49. },
  50. };
  51. </script>

Cascader 级联选择 - 图7

移入展开

通过移入展开下级菜单,点击完成选择。

  1. <template>
  2. <a-cascader
  3. :options="options"
  4. :displayRender="displayRender"
  5. expandTrigger="hover"
  6. @change="onChange"
  7. placeholder="Please select"
  8. />
  9. </template>
  10. <script>
  11. export default {
  12. data() {
  13. return {
  14. options: [
  15. {
  16. value: 'zhejiang',
  17. label: 'Zhejiang',
  18. children: [
  19. {
  20. value: 'hangzhou',
  21. label: 'Hangzhou',
  22. children: [
  23. {
  24. value: 'xihu',
  25. label: 'West Lake',
  26. },
  27. ],
  28. },
  29. ],
  30. },
  31. {
  32. value: 'jiangsu',
  33. label: 'Jiangsu',
  34. children: [
  35. {
  36. value: 'nanjing',
  37. label: 'Nanjing',
  38. children: [
  39. {
  40. value: 'zhonghuamen',
  41. label: 'Zhong Hua Men',
  42. },
  43. ],
  44. },
  45. ],
  46. },
  47. ],
  48. };
  49. },
  50. methods: {
  51. onChange(value) {
  52. console.log(value);
  53. },
  54. displayRender({ labels }) {
  55. return labels[labels.length - 1];
  56. },
  57. },
  58. };
  59. </script>

Cascader 级联选择 - 图8

动态加载选项

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

注意:loadDatashowSearch 无法一起使用。

  1. <template>
  2. <a-cascader
  3. :options="options"
  4. @change="onChange"
  5. :loadData="loadData"
  6. placeholder="Please select"
  7. changeOnSelect
  8. />
  9. </template>
  10. <script>
  11. export default {
  12. data() {
  13. return {
  14. options: [
  15. {
  16. value: 'zhejiang',
  17. label: 'Zhejiang',
  18. isLeaf: false,
  19. },
  20. {
  21. value: 'jiangsu',
  22. label: 'Jiangsu',
  23. isLeaf: false,
  24. },
  25. ],
  26. };
  27. },
  28. methods: {
  29. onChange(value) {
  30. console.log(value);
  31. },
  32. loadData(selectedOptions) {
  33. const targetOption = selectedOptions[selectedOptions.length - 1];
  34. targetOption.loading = true;
  35. // load options lazily
  36. setTimeout(() => {
  37. targetOption.loading = false;
  38. targetOption.children = [
  39. {
  40. label: `${targetOption.label} Dynamic 1`,
  41. value: 'dynamic1',
  42. },
  43. {
  44. label: `${targetOption.label} Dynamic 2`,
  45. value: 'dynamic2',
  46. },
  47. ];
  48. this.options = [...this.options];
  49. }, 1000);
  50. },
  51. },
  52. };
  53. </script>

Cascader 级联选择 - 图9

搜索

可以直接搜索选项并选择。

Cascader[showSearch] 暂不支持服务端搜索,更多信息见 #5547

  1. <template>
  2. <a-cascader
  3. :options="options"
  4. :showSearch="{filter}"
  5. @change="onChange"
  6. placeholder="Please select"
  7. />
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. options: [
  14. {
  15. value: 'zhejiang',
  16. label: 'Zhejiang',
  17. children: [
  18. {
  19. value: 'hangzhou',
  20. label: 'Hangzhou',
  21. children: [
  22. {
  23. value: 'xihu',
  24. label: 'West Lake',
  25. },
  26. {
  27. value: 'xiasha',
  28. label: 'Xia Sha',
  29. disabled: true,
  30. },
  31. ],
  32. },
  33. ],
  34. },
  35. {
  36. value: 'jiangsu',
  37. label: 'Jiangsu',
  38. children: [
  39. {
  40. value: 'nanjing',
  41. label: 'Nanjing',
  42. children: [
  43. {
  44. value: 'zhonghuamen',
  45. label: 'Zhong Hua men',
  46. },
  47. ],
  48. },
  49. ],
  50. },
  51. ],
  52. };
  53. },
  54. methods: {
  55. onChange(value, selectedOptions) {
  56. console.log(value, selectedOptions);
  57. },
  58. filter(inputValue, path) {
  59. return path.some(
  60. option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1,
  61. );
  62. },
  63. },
  64. };
  65. </script>

Cascader 级联选择 - 图10

大小

不同大小的级联选择器。

  1. <template>
  2. <div>
  3. <a-cascader size="large" :options="options" @change="onChange" /><br /><br />
  4. <a-cascader :options="options" @change="onChange" /><br /><br />
  5. <a-cascader size="small" :options="options" @change="onChange" /><br /><br />
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. data() {
  11. return {
  12. options: [
  13. {
  14. value: 'zhejiang',
  15. label: 'Zhejiang',
  16. children: [
  17. {
  18. value: 'hangzhou',
  19. label: 'Hangzhou',
  20. children: [
  21. {
  22. value: 'xihu',
  23. label: 'West Lake',
  24. },
  25. ],
  26. },
  27. ],
  28. },
  29. {
  30. value: 'jiangsu',
  31. label: 'Jiangsu',
  32. children: [
  33. {
  34. value: 'nanjing',
  35. label: 'Nanjing',
  36. children: [
  37. {
  38. value: 'zhonghuamen',
  39. label: 'Zhong Hua Men',
  40. },
  41. ],
  42. },
  43. ],
  44. },
  45. ],
  46. };
  47. },
  48. methods: {
  49. onChange(value) {
  50. console.log(value);
  51. },
  52. },
  53. };
  54. </script>

Cascader 级联选择 - 图11

自定义字段名

自定义字段名。

  1. <template>
  2. <a-cascader
  3. :fieldNames="{ label: 'name', value: 'code', children: 'items' }"
  4. :options="options"
  5. @change="onChange"
  6. placeholder="Please select"
  7. />
  8. </template>
  9. <script>
  10. const options = [
  11. {
  12. code: 'zhejiang',
  13. name: 'Zhejiang',
  14. items: [
  15. {
  16. code: 'hangzhou',
  17. name: 'Hangzhou',
  18. items: [
  19. {
  20. code: 'xihu',
  21. name: 'West Lake',
  22. },
  23. ],
  24. },
  25. ],
  26. },
  27. {
  28. code: 'jiangsu',
  29. name: 'Jiangsu',
  30. items: [
  31. {
  32. code: 'nanjing',
  33. name: 'Nanjing',
  34. items: [
  35. {
  36. code: 'zhonghuamen',
  37. name: 'Zhong Hua Men',
  38. },
  39. ],
  40. },
  41. ],
  42. },
  43. ];
  44. export default {
  45. data() {
  46. return {
  47. options,
  48. };
  49. },
  50. methods: {
  51. onChange(value) {
  52. console.log(value);
  53. },
  54. },
  55. };
  56. </script>

Cascader 级联选择 - 图12

后缀图标

省市区级联。

  1. <template>
  2. <div>
  3. <a-cascader
  4. style="margin-top: 1rem"
  5. :options="options"
  6. @change="onChange"
  7. placeholder="Please select"
  8. >
  9. <a-icon type="smile" slot="suffixIcon" class="test" />
  10. </a-cascader>
  11. <a-cascader
  12. suffixIcon="ab"
  13. style="margin-top: 1rem"
  14. :options="options"
  15. @change="onChange"
  16. placeholder="Please select"
  17. />
  18. </div>
  19. </template>
  20. <script>
  21. export default {
  22. data() {
  23. return {
  24. options: [
  25. {
  26. value: 'zhejiang',
  27. label: 'Zhejiang',
  28. children: [
  29. {
  30. value: 'hangzhou',
  31. label: 'Hangzhou',
  32. children: [
  33. {
  34. value: 'xihu',
  35. label: 'West Lake',
  36. },
  37. ],
  38. },
  39. ],
  40. },
  41. {
  42. value: 'jiangsu',
  43. label: 'Jiangsu',
  44. children: [
  45. {
  46. value: 'nanjing',
  47. label: 'Nanjing',
  48. children: [
  49. {
  50. value: 'zhonghuamen',
  51. label: 'Zhong Hua Men',
  52. },
  53. ],
  54. },
  55. ],
  56. },
  57. ],
  58. };
  59. },
  60. methods: {
  61. onChange(value) {
  62. console.log(value);
  63. },
  64. },
  65. };
  66. </script>

API

  1. <a-cascader :options="options" @change="onChange" />
参数说明类型默认值
allowClear是否支持清除booleantrue
autoFocus自动获取焦点booleanfalse
changeOnSelect当此项为 true 时,点选每级菜单选项值都会发生变化,具体见上面的演示booleanfalse
defaultValue默认的选中项string[] | number[][]
disabled禁用booleanfalse
displayRender选择后展示的渲染函数,可使用 slot="displayRender" 和 slot-scope="{labels, selectedOptions}"({labels, selectedOptions}) => vNodelabels => labels.join(' / ')
expandTrigger次级菜单的展开方式,可选 'click' 和 'hover'string'click'
fieldNames自定义 options 中 label name children 的字段object{ label: 'label', value: 'value', children: 'children' }
getPopupContainer菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。Function(triggerNode)() => document.body
loadData用于动态加载选项,无法与 showSearch 一起使用(selectedOptions) => void-
notFoundContent当下拉列表为空时显示的内容string'Not Found'
options可选项数据源object-
placeholder输入框占位文本string'请选择'
popupClassName自定义浮层类名string-
popupStyle自定义浮层样式object{}
popupPlacement浮层预设位置:bottomLeft bottomRight topLeft topRightEnumbottomLeft
popupVisible控制浮层显隐boolean-
showSearch在选择框中显示搜索框booleanfalse
size输入框大小,可选 large default smallstringdefault
suffixIcon自定义的选择框后缀图标string | VNode | slot-
value(v-model)指定选中项string[] | number[]-

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

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

事件

事件名称说明回调参数
change选择完成后的回调(value, selectedOptions) => void
popupVisibleChange显示/隐藏浮层的回调(value) => void

方法

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

注意,如果需要获得中国省市区数据,可以参考 react 组件的实现 china-division