鸿蒙OS ArkTS 省市县级联选择框,封装组件

背景:

公司现在要开发纯血鸿蒙版本APP,我被抽调过来做点功能。现在要做一个省市县级联选择框,并且要封装为组件,供其他页面模块使用。

效果图:

难点:

1. 现在官方文档上只是查到了TextPicker组件是可以做这样级联选择的效果

2. 这种弹窗,官方文档上是有半模态转场,只是这个半模态是一个严格和宿主节点绑定在一起的弹窗,需要绑定在触发的地方,才可以触发弹出,而且半模态转场中的bindSheet,需要初始化Builder类型装饰器(即模态框中要展示的内容),只是Builder装饰器不允许在组件外调用。

实现:

1. 创建一个组件,组件中内容包括选择器所需要的数据数组、选择器TextPicker所在的Builder装饰器,在TextPicker中去实现级联效果、组件build主体;通过状态(Link、State)来实现在目标页面调用选择器组件

2. 数据数组包括省市县的数据,可以静态写,也可以读取数据文件,我这是读的他们提供的地区xml文件

3. Builder装饰器是半模态专场初始化时的模态框中的内容,其中包括弹框顶部 “取消”、弹窗标题、“确定”布局和事件,下边的省市县三级选择器

@Builder
  selectRegion() {
    Column() {
      Flex({
        justifyContent: FlexAlign.SpaceBetween,
        alignItems: ItemAlign.Center
      }) {
        Text($r('app.string.cancel_txt'))
          .width('36lpx')
          .fontColor('#4976EE')
          .onClick(() => {
            this.showSheet = false;
          })

        Text(this.title)
          .fontColor('#000')
          .fontSize(18)
          .fontWeight(600)

        Text($r('app.string.ok_txt'))
          .width('36lpx')
          .fontColor('#4976EE')
          .onClick(() => {
            this.showSheet = false;
            if (this.okCallback) {
              this.okCallback(this.values);
            }
          })
      }
      .width('92%')
      .height('36lpx')
      .margin({ left: '4%', right: '4%', top: '6lpx' })

      TextPicker({
        range: this.range, //['北京', '北京市', '东城区']
        selected: $$this.selected, //[0, 0, 0]
      })
        .canLoop(false)// 不要循环
        .onChange((values) => {
          //进行防抖处理,防止滚动期间多次发送请求
          clearTimeout(this.timeId)
          this.timeId = setTimeout(async () => {
            let p = this.getProvince(values[0]);
            //当省份被改变
            if (this.values[0] !== values[0]) {

              this.range[1] = this.getCityArray(p.city) //市
              this.range[2] = this.getDistrictArray(p.city) //区

              //当省份发生变化需要把城市置零,当城市发生变化需要把地区置零
              this.selected[1] = 0
              this.selected[2] = 0

              //内容页面展示需要同步
              this.values[0] = values[0]
              this.values[1] = this.range[1][0]
              this.values[2] = this.range[2][0]

              //当城市被改变
            } else if (this.values[1] !== values[1]) {
              this.range[2] = this.getDistrictArrayByName(values[1], p.city) //区

              //当城市发生变化需要把地区置零
              this.selected[2] = 0

              //内容页面展示需要同步
              this.values[1] = values[1]
              this.values[2] = this.range[2][0]

              //当地区被改变
            } else if (this.values[2] !== values[2]) {

              //内容页面展示需要同步
              this.values[2] = values[2]
            }

          }, 100)
        })
    }

  }

4. 组件build主体,是封装的组件主体,是将来要放到要使用此组件的页面中的。在此主体中,绑定初始了半模态框,并定义了半模态框的一些样式

build() {
    Column()
      .bindSheet($$this.showSheet, this.selectRegion(), {
        height: 260,
        showClose: false,
        shouldDismiss: ((sheetDismiss: SheetDismiss) => {
          console.log("bind sheet shouldDismiss")
          //sheetDismiss.dismiss()
        }),
        onWillDismiss: ((DismissSheetAction: DismissSheetAction) => {

        })
      })
  }

5.组件中状态和回调函数

  @Link range: string[][] //TextPicker的values数组 [[], [], []]
  @Link selected: number[] //TextPicker的index数组
  @Link values: string[] //选中后用于展示的数组 ['北京', '北京市', '东城区']
  @Link showSheet: boolean; //半模态框
  @Link title: string;
  timeId: number = -1 //防抖处理的延时器Id
  private okCallback?: (values: string[]) => void

6.在页面中引入并触发显示弹框组件

import { AreaRegion } from '../../model/AreaRegion'

......

 @State isShowSelectRegion: boolean = false;

 showAreagion() {
        this.isShowSelectRegion = true;
  }

build() {
    Column() {
      ......
      AreaRegion({
        showSheet: $isShowSelectRegion,
        title: $regionSelectTitle,
        values: $regionData,
        selected: $regionSelected,
        range: $regionRange,
        okCallback: (values) => {
          /*更新账号所属地区*/
          let region = values[0] + values[1] + values[2]
          console.info(region)
          }).catch((msg: string) => {

          })
        }
      });

        Button('选择省市区')
          .width('60%')
          .margin({ left: '20%' })
          .fontColor('#fff')
          .fontSize('22fp')
          .backgroundColor('#2E74FE')
          .onClick(() => {
             this.showAreagion();
          })

    }
}

7。这种做法感觉不是那么标准,因为是要在所使用的页面UI中先加载AreaRegion组件,然后再通过改变@State变量,传递到组件中,实现组件的展示与否。不过现在暂时没有想到其他方案,如果好办法,欢迎交流。

8.注意文中所贴代码不是全部的代码,可以参考这种方式以及重要实现步骤。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
好的,以下是使用`el-cascader`和Vue3封装省市级联组件示例代码: ```vue <template> <el-cascader :options="options" :props="{ value: 'name', label: 'name', children: 'children' }" :change-on-select="true" v-model="selectedValues" @change="handleChange" /> </template> <script> import { reactive, toRefs } from 'vue' import { getCities } from '@/api/city' // 此处需要自己实现获取城市数据的方法 export default { setup() { const state = reactive({ options: [], selectedValues: [], }) // 初始化省市数据 const initOptions = async () => { const provinces = await getCities() state.options = provinces.map(province => ({ name: province.name, children: province.cities.map(city => ({ name: city.name, children: city.districts.map(district => ({ name: district.name, })), })), })) } // 监听选中值的变化 const handleChange = (value) => { state.selectedValues = value // 在这里可以触发选中值变化的回调函数 } // 初始化省市数据 initOptions() // 返回 selectedValues 和 handleChange,以便在父组件中使用 return { ...toRefs(state), handleChange, } }, } </script> ``` 上述代码中,我们使用了`reactive`和`toRefs`来创建响应式数据,使用`getCities`方法获取省市数据,初始化`options`选项,当选中值发生变化时触发`handleChange`回调函数。在父组件中使用该组件时,只需要监听`selectedValues`和`handleChange`即可。需要注意的是,`getCities`方法需要自己实现,可以从后端接口获取数据或者使用本地静态文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值