Cascader级联选择

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

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

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

    基本

    省市区级联。

    Cascader级联选择 - 图2

    切换按钮和结果分开。

    1. const options = [
    2. {
    3. value: 'zhejiang',
    4. label: 'Zhejiang',
    5. children: [
    6. {
    7. value: 'hangzhou',
    8. label: 'Hangzhou',
    9. },
    10. ],
    11. },
    12. {
    13. value: 'jiangsu',
    14. label: 'Jiangsu',
    15. children: [
    16. {
    17. value: 'nanjing',
    18. label: 'Nanjing',
    19. },
    20. ],
    21. },
    22. ];
    23. class CitySwitcher extends React.Component {
    24. state = {
    25. text: 'Unselect',
    26. };
    27. onChange = (value, selectedOptions) => {
    28. this.setState({
    29. text: selectedOptions.map(o => o.label).join(', '),
    30. });
    31. };
    32. render() {
    33. return (
    34. <span>
    35. {this.state.text}
    36. &nbsp;
    37. <Cascader options={options} onChange={this.onChange}>
    38. <a href="#">Change city</a>
    39. </Cascader>
    40. </span>
    41. );
    42. }
    43. }
    44. ReactDOM.render(<CitySwitcher />, mountNode);

    禁用选项

    通过指定 options 里的 disabled 字段。

    1. import { Cascader } from 'antd';
    2. const options = [
    3. {
    4. value: 'zhejiang',
    5. label: 'Zhejiang',
    6. children: [
    7. {
    8. value: 'hangzhou',
    9. label: 'Hangzhou',
    10. children: [
    11. {
    12. value: 'xihu',
    13. label: 'West Lake',
    14. },
    15. ],
    16. },
    17. ],
    18. },
    19. {
    20. value: 'jiangsu',
    21. label: 'Jiangsu',
    22. disabled: true,
    23. children: [
    24. {
    25. value: 'nanjing',
    26. label: 'Nanjing',
    27. children: [
    28. {
    29. value: 'zhonghuamen',
    30. label: 'Zhong Hua Men',
    31. },
    32. ],
    33. },
    34. ],
    35. },
    36. ];
    37. function onChange(value) {
    38. console.log(value);
    39. }
    40. ReactDOM.render(<Cascader options={options} onChange={onChange} />, mountNode);

    不同大小的级联选择器。

    1. import { Cascader } from 'antd';
    2. const options = [
    3. {
    4. value: 'zhejiang',
    5. label: 'Zhejiang',
    6. children: [
    7. {
    8. value: 'hangzhou',
    9. label: 'Hangzhou',
    10. children: [
    11. {
    12. value: 'xihu',
    13. label: 'West Lake',
    14. },
    15. ],
    16. },
    17. ],
    18. },
    19. {
    20. value: 'jiangsu',
    21. label: 'Jiangsu',
    22. children: [
    23. {
    24. value: 'nanjing',
    25. label: 'Nanjing',
    26. children: [
    27. {
    28. value: 'zhonghuamen',
    29. label: 'Zhong Hua Men',
    30. },
    31. ],
    32. },
    33. ],
    34. },
    35. ];
    36. function onChange(value) {
    37. console.log(value);
    38. }
    39. ReactDOM.render(
    40. <div>
    41. <Cascader size="large" options={options} onChange={onChange} />
    42. <br />
    43. <Cascader options={options} onChange={onChange} />
    44. <br />
    45. <br />
    46. <Cascader size="small" options={options} onChange={onChange} />
    47. <br />
    48. <br />
    49. </div>,
    50. mountNode,
    51. );

    Cascader级联选择 - 图5

    搜索

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

    自定义字段名。

    1. import { Cascader } from 'antd';
    2. {
    3. code: 'zhejiang',
    4. name: 'Zhejiang',
    5. items: [
    6. {
    7. code: 'hangzhou',
    8. name: 'Hangzhou',
    9. items: [
    10. {
    11. code: 'xihu',
    12. name: 'West Lake',
    13. },
    14. ],
    15. },
    16. ],
    17. },
    18. {
    19. code: 'jiangsu',
    20. name: 'Jiangsu',
    21. items: [
    22. {
    23. code: 'nanjing',
    24. name: 'Nanjing',
    25. items: [
    26. {
    27. code: 'zhonghuamen',
    28. name: 'Zhong Hua Men',
    29. },
    30. ],
    31. },
    32. ],
    33. },
    34. ];
    35. function onChange(value) {
    36. console.log(value);
    37. }
    38. ReactDOM.render(
    39. <Cascader
    40. fieldNames={{ label: 'name', value: 'code', children: 'items' }}
    41. options={options}
    42. onChange={onChange}
    43. placeholder="Please select"
    44. />,
    45. mountNode,
    46. );

    Cascader级联选择 - 图7

    默认值

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

    1. import { Cascader } from 'antd';
    2. const options = [
    3. {
    4. value: 'zhejiang',
    5. label: 'Zhejiang',
    6. children: [
    7. {
    8. value: 'hangzhou',
    9. label: 'Hangzhou',
    10. children: [
    11. {
    12. value: 'xihu',
    13. label: 'West Lake',
    14. },
    15. ],
    16. },
    17. ],
    18. },
    19. {
    20. value: 'jiangsu',
    21. label: 'Jiangsu',
    22. children: [
    23. {
    24. value: 'nanjing',
    25. label: 'Nanjing',
    26. children: [
    27. {
    28. value: 'zhonghuamen',
    29. label: 'Zhong Hua Men',
    30. },
    31. ],
    32. },
    33. ],
    34. },
    35. ];
    36. function onChange(value) {
    37. console.log(value);
    38. }
    39. ReactDOM.render(
    40. <Cascader
    41. defaultValue={['zhejiang', 'hangzhou', 'xihu']}
    42. options={options}
    43. onChange={onChange}
    44. />,
    45. mountNode,
    46. );

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

    1. import { Cascader } from 'antd';
    2. const options = [
    3. {
    4. value: 'zhejiang',
    5. label: 'Zhejiang',
    6. children: [
    7. {
    8. value: 'hangzhou',
    9. label: 'Hangzhou',
    10. children: [
    11. {
    12. value: 'xihu',
    13. label: 'West Lake',
    14. },
    15. ],
    16. },
    17. ],
    18. },
    19. {
    20. value: 'jiangsu',
    21. label: 'Jiangsu',
    22. children: [
    23. {
    24. value: 'nanjing',
    25. label: 'Nanjing',
    26. children: [
    27. {
    28. value: 'zhonghuamen',
    29. label: 'Zhong Hua Men',
    30. },
    31. ],
    32. },
    33. ],
    34. },
    35. function onChange(value) {
    36. console.log(value);
    37. }
    38. // Just show the latest item.
    39. function displayRender(label) {
    40. return label[label.length - 1];
    41. }
    42. ReactDOM.render(
    43. <Cascader
    44. options={options}
    45. expandTrigger="hover"
    46. displayRender={displayRender}
    47. onChange={onChange}
    48. />,
    49. mountNode,
    50. );

    选择即改变

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

    Cascader级联选择 - 图10

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

    1. const options = [
    2. {
    3. value: 'zhejiang',
    4. label: 'Zhejiang',
    5. children: [
    6. {
    7. value: 'hangzhou',
    8. label: 'Hangzhou',
    9. children: [
    10. {
    11. value: 'xihu',
    12. label: 'West Lake',
    13. code: 752100,
    14. },
    15. ],
    16. },
    17. ],
    18. },
    19. {
    20. value: 'jiangsu',
    21. label: 'Jiangsu',
    22. children: [
    23. {
    24. value: 'nanjing',
    25. label: 'Nanjing',
    26. children: [
    27. {
    28. value: 'zhonghuamen',
    29. label: 'Zhong Hua Men',
    30. code: 453400,
    31. },
    32. ],
    33. },
    34. ],
    35. },
    36. ];
    37. function handleAreaClick(e, label, option) {
    38. e.stopPropagation();
    39. console.log('clicked', label, option);
    40. }
    41. const displayRender = (labels, selectedOptions) =>
    42. labels.map((label, i) => {
    43. const option = selectedOptions[i];
    44. if (i === labels.length - 1) {
    45. return (
    46. <span key={option.value}>
    47. {label} (<a onClick={e => handleAreaClick(e, label, option)}>{option.code}</a>)
    48. </span>
    49. );
    50. }
    51. return <span key={option.value}>{label} / </span>;
    52. });
    53. ReactDOM.render(
    54. <Cascader
    55. options={options}
    56. defaultValue={['zhejiang', 'hangzhou', 'xihu']}
    57. displayRender={displayRender}
    58. style={{ width: '100%' }}
    59. />,
    60. mountNode,
    61. );

    动态加载选项

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

    1. import { Cascader } from 'antd';
    2. const options = [
    3. {
    4. value: 'zhejiang',
    5. label: 'Zhejiang',
    6. isLeaf: false,
    7. },
    8. {
    9. value: 'jiangsu',
    10. label: 'Jiangsu',
    11. isLeaf: false,
    12. },
    13. ];
    14. class LazyOptions extends React.Component {
    15. state = {
    16. options,
    17. };
    18. onChange = (value, selectedOptions) => {
    19. console.log(value, selectedOptions);
    20. };
    21. loadData = selectedOptions => {
    22. const targetOption = selectedOptions[selectedOptions.length - 1];
    23. targetOption.loading = true;
    24. // load options lazily
    25. setTimeout(() => {
    26. targetOption.loading = false;
    27. targetOption.children = [
    28. {
    29. label: `${targetOption.label} Dynamic 1`,
    30. value: 'dynamic1',
    31. },
    32. {
    33. label: `${targetOption.label} Dynamic 2`,
    34. value: 'dynamic2',
    35. },
    36. ];
    37. this.setState({
    38. options: [...this.state.options],
    39. });
    40. }, 1000);
    41. };
    42. render() {
    43. return (
    44. <Cascader
    45. options={this.state.options}
    46. loadData={this.loadData}
    47. onChange={this.onChange}
    48. changeOnSelect
    49. />
    50. );
    51. }
    52. }
    1. <Cascader options="{options}" onChange="{onChange}" />