CascaderSelect 级联选择

如果项目中使用的是 1.x 版本的基础组件(@alifd/next),请在左侧导航顶部切换组件版本。

安装方法

  1. 在命令行中执行以下命令npm install @icedesign/base@latest -S

开发指南

何时使用

级联选择由选择器级联组成。把级联组件以弹层的方式隐藏,多用于表单场景。

API

级联选择

参数说明类型默认值
prefix样式类名的品牌前缀String'next-'
className自定义类名String-
style自定义内联样式Object-
size选择框大小可选值:'small', 'medium', 'large'Enum'medium'
shape选择框形状可选值:'normal', 'arrow-only'Enum'normal'
placeholder选择框占位符String-
disabled是否禁用Booleanfalse
hasArrow是否显示右侧的箭头Booleantrue
hasClear是否显示清空按钮,该按钮可以清空当前选中的值,该属性仅在单选模式下有效Booleanfalse
dataSource数据源,结构可参考下方说明Array<Object>[]
defaultValue(非受控)默认值String/Array<String>null
value(受控)当前值String/Array<String>-
onChange选中值改变时触发的回调函数签名:Function(value: String/Array, data: Object/Array, extra: Object) => void参数:value: {String/Array} 选中的值,单选时返回单个值,多选时返回数组data: {Object/Array} 选中的数据,包括 value 和 label,单选时返回单个值,多选时返回数组,父子节点选中关联时,同时选中,只返回父节点extra: {Object} 额外参数extra.selectedPath: {Array} 单选时选中的数据的路径extra.checked: {Boolean} 多选时当前的操作是选中还是取消选中extra.currentData: {Object} 多选时当前操作的数据extra.checkedData: {Array} 多选时所有被选中的数据extra.indeterminateData: {Array} 多选时半选的数据Function-
defaultVisible初始下拉框是否显示Booleanfalse
defaultExpandedValue默认展开值,如果不设置,组件内部会根据 defaultValue/value 进行自动设置Array<String>-
expandTrigger展开触发的方式可选值:'click', 'hover'Enum'click'
multiple是否多选Booleanfalse
changeOnSelect是否选中即发生改变, 该属性仅在单选模式下有效Booleanfalse
canOnlyCheckLeaf是否只能勾选叶子项的checkbox,该属性仅在多选模式下有效Booleanfalse
checkStrictly父子节点是否选中不关联Booleanfalse
labelWidth文字区域宽度,当文字超过宽度时,结尾会以省略号显示,默认值为文字实际宽度String/Number-
showItemCount每一列展示的个数String/Number6
displayRender选择框单选时展示结果的函数签名:Function(label: Array) => ReactNode参数:label: {Array} 选中路径的文本数组返回值:{ReactNode} 渲染在选择框中的内容Functionlabel => label.join(' / ')
popupClassName下拉框样式自定义类名String-
container下拉框挂载的容器节点String/Function-
loadData异步加载数据函数签名:Function(data: Object) => void参数:data: {Object} 当前点击异步加载的数据Function-

代码示例

基本使用

展示基本的单选用法。

CascaderSelect 级联选择 - 图1

查看源码在线预览

  1. import { CascaderSelect } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. data: []
  7. };
  8. this.handleChange = this.handleChange.bind(this);
  9. }
  10. componentDidMount() {
  11. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  12. .then(response => response.json())
  13. .then(data => {
  14. data[1].disabled = true;
  15. this.setState({ data });
  16. })
  17. .catch(e => console.log(e));
  18. }
  19. handleChange(value, data, extra) {
  20. console.log(value, data, extra);
  21. }
  22. render() {
  23. return (
  24. <CascaderSelect
  25. dataSource={this.state.data}
  26. onChange={this.handleChange}
  27. />
  28. );
  29. }
  30. }
  31. ReactDOM.render(<Demo />, mountNode);

自定义样式

可以通过displayRender来定制单选时展示的结果,可以通过labelWidth, showItemCount来定制组件宽高,其中通过labelWidth可设置文字区域宽度,当文字超过宽度时,结尾会以省略号显示,默认值为文字实际宽度,通过showItemCount可设置展示的菜单项个数。

CascaderSelect 级联选择 - 图2

查看源码在线预览

  1. import { CascaderSelect } from "@icedesign/base";
  2. const dataSource = [
  3. {
  4. value: "2973",
  5. label: "陕西",
  6. children: [
  7. {
  8. value: "2974",
  9. label: "西安",
  10. children: [
  11. { value: "2975", label: "西安市" },
  12. { value: "2976", label: "高陵县" }
  13. ]
  14. },
  15. {
  16. value: "2980",
  17. label: "铜川",
  18. children: [
  19. { value: "2981", label: "铜川市" },
  20. { value: "2982", label: "宜君县" }
  21. ]
  22. }
  23. ]
  24. },
  25. {
  26. value: "3371",
  27. label: "新疆",
  28. children: [
  29. {
  30. value: "3430",
  31. label: "巴音郭楞蒙古自治州",
  32. children: [
  33. { value: "3431", label: "库尔勒市" },
  34. { value: "3432", label: "和静县" }
  35. ]
  36. }
  37. ]
  38. }
  39. ];
  40. const displayRender = labels => {
  41. return labels.reduce((ret, label, index) => {
  42. ret.push(
  43. <span className="label-ellipsis" title={label}>
  44. {label}
  45. </span>
  46. );
  47. if (index < labels.length - 1) {
  48. ret.push(<span className="label-separator"> / </span>);
  49. }
  50. return ret;
  51. }, []);
  52. };
  53. ReactDOM.render(
  54. <CascaderSelect
  55. style={{ width: "240px" }}
  56. displayRender={displayRender}
  57. showItemCount="5"
  58. labelWidth="80"
  59. defaultValue="3431"
  60. dataSource={dataSource}
  61. />,
  62. mountNode
  63. );
  1. .label-ellipsis {
  2. display: inline-block;
  3. max-width: 80px;
  4. overflow: hidden;
  5. text-overflow: ellipsis;
  6. white-space: nowrap;
  7. word-wrap: normal;
  8. }
  9. .label-separator {
  10. display: inline-block;
  11. vertical-align: top;
  12. margin: 0 5px;
  13. }

异步加载数据

展示动态获取数据的用法。

CascaderSelect 级联选择 - 图3

查看源码在线预览

  1. import { CascaderSelect } from "@icedesign/base";
  2. const dataSource = [
  3. {
  4. value: "2973",
  5. label: "陕西"
  6. }
  7. ];
  8. class Demo extends React.Component {
  9. constructor(props) {
  10. super(props);
  11. this.state = {
  12. dataSource
  13. };
  14. this.onLoadData = this.onLoadData.bind(this);
  15. }
  16. onLoadData(data) {
  17. console.log(data);
  18. return new Promise(resolve => {
  19. setTimeout(() => {
  20. this.setState(
  21. {
  22. dataSource: [
  23. {
  24. value: "2973",
  25. label: "陕西",
  26. children: [
  27. {
  28. value: "2974",
  29. label: "西安",
  30. children: [
  31. { value: "2975", label: "西安市", isLeaf: true },
  32. { value: "2976", label: "高陵县", isLeaf: true }
  33. ]
  34. },
  35. {
  36. value: "2980",
  37. label: "铜川",
  38. children: [
  39. { value: "2981", label: "铜川市", isLeaf: true },
  40. { value: "2982", label: "宜君县", isLeaf: true }
  41. ]
  42. }
  43. ]
  44. }
  45. ]
  46. },
  47. resolve
  48. );
  49. }, 500);
  50. });
  51. }
  52. render() {
  53. return (
  54. <CascaderSelect
  55. dataSource={this.state.dataSource}
  56. loadData={this.onLoadData}
  57. />
  58. );
  59. }
  60. }
  61. ReactDOM.render(<Demo />, mountNode);

展开触发行为

展示可通过expandTrigger来设置不同的展开触发行为,支持clickhover,默认值为click

CascaderSelect 级联选择 - 图4

查看源码在线预览

  1. import { Radio, CascaderSelect } from "@icedesign/base";
  2. const { Group: RadioGroup } = Radio;
  3. class Demo extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. this.state = {
  7. trigger: "click",
  8. data: []
  9. };
  10. this.handleChange = this.handleChange.bind(this);
  11. this.handleChangeTrigger = this.handleChangeTrigger.bind(this);
  12. }
  13. componentDidMount() {
  14. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  15. .then(response => response.json())
  16. .then(data => this.setState({ data }))
  17. .catch(e => console.log(e));
  18. }
  19. handleChange(value, data, extra) {
  20. console.log(value, data, extra);
  21. }
  22. handleChangeTrigger(trigger) {
  23. this.setState({
  24. trigger
  25. });
  26. }
  27. render() {
  28. return (
  29. <div>
  30. <div className="trigger-check">
  31. 展开触发行为:
  32. <RadioGroup
  33. dataSource={["click", "hover"]}
  34. value={this.state.trigger}
  35. onChange={this.handleChangeTrigger}
  36. />
  37. </div>
  38. <CascaderSelect
  39. expandTrigger={this.state.trigger}
  40. dataSource={this.state.data}
  41. onChange={this.handleChange}
  42. />
  43. </div>
  44. );
  45. }
  46. }
  47. ReactDOM.render(<Demo />, mountNode);
  1. .trigger-check {
  2. margin-bottom: 10px;
  3. font-size: 14px;
  4. color: #666;
  5. }

设置父子节点选中是否关联

展示受控多选以及是否开启严格受控父子节点选中不再关联的用法。

CascaderSelect 级联选择 - 图5

查看源码在线预览

  1. import { Checkbox, CascaderSelect } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. value: [],
  7. data: [],
  8. checkStrictly: false
  9. };
  10. this.handleCheck = this.handleCheck.bind(this);
  11. this.handleChange = this.handleChange.bind(this);
  12. }
  13. componentDidMount() {
  14. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  15. .then(response => response.json())
  16. .then(data => this.setState({ data, value: ["2975"] }))
  17. .catch(e => console.log(e));
  18. }
  19. handleCheck() {
  20. this.setState({
  21. checkStrictly: !this.state.checkStrictly,
  22. value: []
  23. });
  24. }
  25. handleChange(value, data, extra) {
  26. console.log(value, data, extra);
  27. this.setState({
  28. value
  29. });
  30. }
  31. render() {
  32. return (
  33. <div className="control-multiple-demo">
  34. <label className="strictly-check">
  35. <Checkbox
  36. value={this.state.checkStrictly}
  37. onChange={this.handleCheck}
  38. />
  39. <span className="strictly-text">
  40. 开启严格受控,父子节点选中不再关联
  41. </span>
  42. </label>
  43. <CascaderSelect
  44. multiple
  45. checkStrictly={this.state.checkStrictly}
  46. value={this.state.value}
  47. dataSource={this.state.data}
  48. onChange={this.handleChange}
  49. />
  50. </div>
  51. );
  52. }
  53. }
  54. ReactDOM.render(<Demo />, mountNode);
  1. .control-multiple-demo .strictly-check {
  2. display: block;
  3. margin-bottom: 10px;
  4. }
  5. .control-multiple-demo .strictly-text {
  6. display: inline-block;
  7. margin-left: 10px;
  8. vertical-align: middle;
  9. color: #666;
  10. font-size: 14px;
  11. }

多选

展示基本的多选用法。

CascaderSelect 级联选择 - 图6

查看源码在线预览

  1. import { CascaderSelect } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. data: []
  7. };
  8. this.handleChange = this.handleChange.bind(this);
  9. }
  10. componentDidMount() {
  11. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  12. .then(response => response.json())
  13. .then(data => {
  14. data[1].disabled = true;
  15. data[2].checkboxDisabled = true;
  16. this.setState({ data });
  17. })
  18. .catch(e => console.log(e));
  19. }
  20. handleChange(value, data, extra) {
  21. console.log(value, data, extra);
  22. }
  23. render() {
  24. return (
  25. <CascaderSelect
  26. multiple
  27. dataSource={this.state.data}
  28. onChange={this.handleChange}
  29. />
  30. );
  31. }
  32. }
  33. ReactDOM.render(<Demo />, mountNode);
  1. .cascader-value {
  2. width: 500px;
  3. margin-bottom: 10px;
  4. font-size: 14px;
  5. color: #666;
  6. }

设置是否只能选择叶子项

展示受控单选以及是否选择即改变。

CascaderSelect 级联选择 - 图7

查看源码在线预览

  1. import { Checkbox, CascaderSelect } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. value: null,
  7. changeOnSelect: false,
  8. data: []
  9. };
  10. this.handleCheck = this.handleCheck.bind(this);
  11. this.handleChange = this.handleChange.bind(this);
  12. }
  13. componentDidMount() {
  14. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  15. .then(response => response.json())
  16. .then(data => this.setState({ data, value: "2975" }))
  17. .catch(e => console.log(e));
  18. }
  19. handleCheck() {
  20. this.setState({
  21. changeOnSelect: !this.state.changeOnSelect,
  22. value: null
  23. });
  24. }
  25. handleChange(value, data, extra) {
  26. console.log(value, data, extra);
  27. this.setState({
  28. value
  29. });
  30. }
  31. render() {
  32. return (
  33. <div className="control-single-demo">
  34. <label className="change-check">
  35. <Checkbox
  36. value={this.state.changeOnSelect}
  37. onChange={this.handleCheck}
  38. />
  39. <span className="change-text">开启选择即改变</span>
  40. </label>
  41. <CascaderSelect
  42. hasClear
  43. changeOnSelect={this.state.changeOnSelect}
  44. value={this.state.value}
  45. dataSource={this.state.data}
  46. onChange={this.handleChange}
  47. />
  48. </div>
  49. );
  50. }
  51. }
  52. ReactDOM.render(<Demo />, mountNode);
  1. .control-single-demo .change-check {
  2. display: block;
  3. margin-bottom: 10px;
  4. }
  5. .control-single-demo .change-text {
  6. display: inline-block;
  7. margin-left: 10px;
  8. vertical-align: middle;
  9. color: #666;
  10. font-size: 14px;
  11. }

相关区块

CascaderSelect 级联选择 - 图8

暂无相关区块