Cascader 级联

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

安装方法

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

开发指南

何时使用

  • 适用于从一组具有关联性的数据集合中进行选择的交互方式。

  • 由于子集目录隐藏,级联是一种节约屏幕空间的有效方法。

  • 级别数因业务需求而定,建议不超过5级。

  • 级联多用于表单场景,可以独立在页面中使用,也可以与其他元素组合使用,如级联选择。

API

级联

参数说明类型默认值
prefix样式类名的品牌前缀String'next-'
className自定义类名String-
style自定义内联样式Object-
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-
defaultExpandedValue(非受控)默认展开值,如果不设置,组件内部会根据 defaultValue/value 进行自动设置Array<String>-
expandedValue(受控)当前展开值Array<String>-
expandTrigger展开触发的方式可选值:'click', 'hover'Enum'click'
onExpand展开时触发的回调函数签名:Function(expandedValue: Array) => void参数:expandedValue: {Array} 各列展开值的数组Function-
multiple是否多选Booleanfalse
canOnlySelectLeaf单选时是否只能选中叶子节点Booleanfalse
canOnlyCheckLeaf多选时是否只能选中叶子节点Booleanfalse
checkStrictly父子节点是否选中不关联Booleanfalse
labelWidth文字区域宽度,当文字超过宽度时,结尾会以省略号显示,默认值为文字实际宽度String/Number-
showItemCount每一列展示的个数String/Number6
loadData异步加载数据函数签名:Function(data: Object) => void参数:data: {Object} 当前点击异步加载的数据Function-

代码示例

基本使用

展示基本的单选用法。

Cascader 级联 - 图1

查看源码在线预览

  1. import { Cascader } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. label: "",
  7. data: []
  8. };
  9. this.handleChange = this.handleChange.bind(this);
  10. }
  11. componentDidMount() {
  12. fetch("https://os.alipayobjects.com/rmsportal/ODDwqcDFTLAguOvWEolX.json")
  13. .then(response => response.json())
  14. .then(data => {
  15. data[1].disabled = 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. this.setState({
  23. label: extra.selectedPath.map(d => d.label).join(" / ")
  24. });
  25. }
  26. render() {
  27. return (
  28. <div>
  29. <div className="cascader-value">选择:{this.state.label}</div>
  30. <Cascader
  31. dataSource={this.state.data}
  32. defaultValue="2975"
  33. onChange={this.handleChange}
  34. />
  35. </div>
  36. );
  37. }
  38. }
  39. ReactDOM.render(<Demo />, mountNode);
  1. .cascader-value {
  2. margin-bottom: 10px;
  3. font-size: 14px;
  4. color: #666;
  5. }

自定义样式

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

Cascader 级联 - 图2

查看源码在线预览

  1. import { Cascader } 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. ReactDOM.render(
  41. <Cascader
  42. defaultValue="3439"
  43. defaultExpandedValue={["3371", "3430"]}
  44. showItemCount="5"
  45. labelWidth="100"
  46. dataSource={dataSource}
  47. />,
  48. mountNode
  49. );

异步加载数据

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

Cascader 级联 - 图3

查看源码在线预览

  1. import { Cascader } 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. <Cascader
  55. canOnlySelectLeaf
  56. dataSource={this.state.dataSource}
  57. loadData={this.onLoadData}
  58. />
  59. );
  60. }
  61. }
  62. ReactDOM.render(<Demo />, mountNode);
  1. .cascader-value {
  2. margin-bottom: 10px;
  3. font-size: 14px;
  4. color: #666;
  5. }

展开触发行为

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

Cascader 级联 - 图4

查看源码在线预览

  1. import { Radio, Cascader } 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. <Cascader
  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. }

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

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

Cascader 级联 - 图5

查看源码在线预览

  1. import { Checkbox, Cascader } 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. <Cascader
  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. }

多选

展示基本的多选用法。

Cascader 级联 - 图6

查看源码在线预览

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

设置是否只能选择叶子项

展示受控单选以及是否只能选择叶子项的用法。

Cascader 级联 - 图7

查看源码在线预览

  1. import { Checkbox, Cascader } from "@icedesign/base";
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. value: null,
  7. canOnlySelectLeaf: 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. canOnlySelectLeaf: !this.state.canOnlySelectLeaf,
  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="leaf-check">
  35. <Checkbox
  36. value={this.state.canOnlySelectLeaf}
  37. onChange={this.handleCheck}
  38. />
  39. <span className="leaf-text">开启只能选择叶子项</span>
  40. </label>
  41. <Cascader
  42. canOnlySelectLeaf={this.state.canOnlySelectLeaf}
  43. value={this.state.value}
  44. dataSource={this.state.data}
  45. onChange={this.handleChange}
  46. />
  47. </div>
  48. );
  49. }
  50. }
  51. ReactDOM.render(<Demo />, mountNode);
  1. .control-single-demo .leaf-check {
  2. display: block;
  3. margin-bottom: 10px;
  4. }
  5. .control-single-demo .leaf-text {
  6. display: inline-block;
  7. margin-left: 10px;
  8. vertical-align: middle;
  9. color: #666;
  10. font-size: 14px;
  11. }

相关区块

Cascader 级联 - 图8

暂无相关区块