1# 列表的多级联动 2## 场景介绍 3多级联动是指根据一个列表(一级列表)的选择结果,来更新另一个列表(二级列表)的选择项,再来更新第三个列表(三级列表)的选择,以此类推。这种联动可以根据用户的实际需求,快速定位到想要的选项,提高交互体验。例如,省市县三级地区的选择、工作部门的选择,本文即为大家介绍如何开发列表的多级联动。 4 5## 效果呈现 6本例效果图如下: 7 8 9## 运行环境 10 11本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 12- IDE: DevEco Studio 4.0 Release 13- SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release) 14 15## 实现思路 16本例关键功能点及其实现思路如下: 17- 文本选择弹窗:通过CompanyDialogController实现。 18 19- 点击公司列表弹出对应旗下子公司的列表,点击子公司列表弹出对应的旗下部门的网格:通过ForEach的嵌套使用进行循环渲染公司列表、子公司列表、部门。 20 21## 开发步骤 22根据实现思路,具体开发步骤如下: 231. 构建列表数据。 24 25 ```ts 26 // LinkageData.ets 27 export interface Link{ 28 name:string 29 Subsidiary:a[] 30 } 31 export interface a{ 32 name:string, 33 department:Array<string> 34 } 35 export const LinkageData:Link[]=[ 36 { 37 name:"A公司", 38 Subsidiary:[ 39 { 40 name:"a子公司", 41 department:[ 42 "技术部", 43 "工程部", 44 "维护部", 45 "运营部", 46 "售后部" 47 ] 48 }, 49 { 50 name:"b子公司", 51 department:[ 52 "行政部", 53 "管理部", 54 "服务部", 55 "秘书部" 56 ] 57 }, 58 { 59 name:"c子公司", 60 department:[ 61 "行动部", 62 "情报部", 63 "信息部" 64 ] 65 } 66 ] 67 }, 68 ... 69 ] 70 ``` 712. 打开自定义弹窗。通过CustomDialogController以实现自定义弹窗的打开。 72 73 ```ts 74 // Index.ets 75 ... 76 CompanyDialogController:CustomDialogController = new CustomDialogController({ 77 builder:CompanyPicker({ 78 postA:$postA, 79 company:$companyButtonTitle, 80 companyStringArray:this.CompanyArray 81 }), 82 autoCancel:true, 83 alignment:DialogAlignment.Bottom, 84 customStyle:true 85 }) 86 87 build() { 88 Column(){ 89 Text(this.companyButtonTitle) 90 .height(50) 91 .fontSize(30) 92 .borderRadius(10) 93 .backgroundColor(0xFFFFFF) 94 .onClick(()=>{ 95 this.CompanyDialogController.open(); 96 }) 97 }.width('100%').height('100%') 98 .backgroundColor(Color.White) 99 .padding({top:5}) 100 } 101 ... 102 ``` 1033. 具体部门的选择。通过ForEach的嵌套使用循环渲染公司列表、子公司列表、部门。通过点击事件将具体部门展示到弹窗上方,点击确定后,界面显示具体部门。 104 105 ```ts 106 // Index.ets 107 ... 108 List({space:15, initialIndex:0,scroller:this.scroller}){ 109 ForEach(LinkageData,(Item:Link)=>{ 110 ListItem() { 111 Column() { 112 Text(`${Item.name === '' ? Item : Item.name}`) 113 .height(40) 114 .fontSize(30) 115 .fontColor('#000000') 116 .width('100%') 117 .margin({ top: 10 }) 118 .onClick(() => { 119 if (this.isCompany === Item.name) { 120 this.isCompany = '' 121 } else { 122 this.isCompany = Item.name 123 } 124 }) 125 if (this.isCompany === Item.name) { 126 List({ space: 10 }) { 127 ForEach(Item.Subsidiary, (ItemA: a) => { 128 ListItem() { 129 Column() { 130 Text(`${Item.name === undefined ? ItemA : ItemA.name}`) 131 .width('100%') 132 .height(20) 133 .fontSize(18) 134 .margin({ top: 4 }) 135 .onClick(() => { 136 if (this.isSubsidiaryAA === ItemA.name) { 137 this.isSubsidiaryAA = '' 138 } else { 139 this.isSubsidiaryAA = ItemA.name 140 } 141 }) 142 if (this.isSubsidiaryAA === ItemA.name) { 143 Grid() { 144 ForEach(ItemA.department, (departmentName: string) => { 145 GridItem() { 146 Text(`${departmentName}`) 147 .margin({ top: 10, bottom: 10 }) 148 .fontSize(14) 149 .maxLines(5) 150 .fontColor(Color.Black) 151 .borderRadius(5) 152 .padding(5) 153 .backgroundColor('#00FFFF') 154 .onClick(() => { 155 this.tempDepartment = `${Item.name}${ItemA.name}${departmentName}` 156 }) 157 } 158 }) 159 }.width('100%') 160 .height(100) 161 .columnsTemplate('1fr 1fr') 162 } 163 } 164 } 165 }) 166 } 167 } 168 } 169 } 170 }) 171 } 172 ... 173 ``` 1744. 自定义弹窗的关闭。 175 176 ```ts 177 // Index.ets 178 ... 179 Row(){ 180 Text(this.tempDepartment) 181 .fontSize(14) 182 .fontColor(Color.White) 183 .layoutWeight(1) 184 .height(40) 185 Button("确定",{type:ButtonType.Normal,stateEffect:true}) 186 .fontSize(14) 187 .fontColor(Color.White) 188 .layoutWeight(1) 189 .height(40) 190 .onClick(()=>{ 191 this.company = this.tempDepartment 192 if (this.controller !== undefined){ 193 this.controller.close() 194 } 195 }) 196 } 197 ... 198 ``` 199## 完整代码 200在LinkageData.ets根据效果开发者自行进行编辑,在Index.ets在开发步骤中基本展示全部代码。 201## 参考 202[自定义弹窗](../application-dev/reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 203 204[循环渲染](../application-dev/quick-start/arkts-rendering-control-foreach.md)