基于vue3和element-plus的省市区级联组件,elui-china-area-dht发布

32 篇文章 2 订阅

说明

其实该组件很简单,核心在于全国省市区数据的来源,还有数据格式化以及组件封装。

然后大家应该知道在vue2阶段其实有一个省市区的第三方封装的组件,我想大家应该不少人使用过。

看源码,作者应该暂时没有发布vue3的计划。那么我这里就提前一步给大家个福利。

使用的话直接看使用部分就行了。

核心原理

数据基于:https://github.com/airyland/china-area-data

根据第三方提供的省市区数据部分,将数据改为element-plus所需的嵌套数据结构

封装ChinaArea类函数

chinaObj将第三方数据改平为一个大对象,可以根据value值进行取值。数据提前赋值给chinaAreaflat

recursion递归函数,支持了增加全部选项(isall)还有控制递归层级leave参数

最终导出得到

chinaAreaData原始数据

ChinaAreaflat改平为对象的数据

关于组件选择之后参数取值问题:

import { EluiChinaAreaDht } from 'elui-china-area-dht'
const chinaData = new EluiChinaAreaDht.ChinaArea().chinaAreaflat
chinaData[得到的value值]

jsx代码

采用高阶函数形式封装,最大限度的保留el-cascader参数的完整性,也就是说除了options参数所有原el-cascader参数都可以使用

import { defineComponent, ref } from 'vue'
import ChinaArea from './ChinaArea'
const EluiChinaAreaDht = defineComponent({
  name: 'EluiChinaAreaDht',
  props: {
    isall: Boolean,
    leave: {
      type: Number,
      default: 3,
    },
  },
  setup(props, ctx) {
    const chinaArea = new ChinaArea({ leave: props.leave, isall: props.isall })

    const options = ref(chinaArea.chinaData())

    return () => <el-cascader {...ctx.attrs} options={options.value} v-slots={ctx.slots} />
  },
})

export default EluiChinaAreaDht

ts代码部分

import chinaAreaData from 'china-area-data'

// 递归子选项
interface Options {
  label: string
  value: string
  leave?: number
  children?: Options[]
}
// 省市区数据结构化定义类型
interface ChinaArr {
  label: string
  parent?: string
  value: string
}
// 递归输入参数
interface InRecursion {
  ssq: { [key: string]: string }
  leave?: number
  custom?: Options
}
interface ChinaAreaInput {
  leave: number
  isall: boolean
  customItem?: Options[]
  after?: boolean
}
interface ChinaAreaflat {
  [key: string]: ChinaArr
}
class ChinaArea {
  chinaAreaData = chinaAreaData
  chinaAreaflat: ChinaAreaflat // 对象改平之后的结构,用于数据取值
  // 将数组结构转化为对象结构
  chinaObj() {
    const list: ChinaAreaflat = {}
    for (const key in chinaAreaData) {
      for (const i in chinaAreaData[key]) {
        const item: ChinaArr = {
          label: chinaAreaData[key][i],
          value: i,
        }
        if (key !== '86') item.parent = key
        list[i] = item
      }
    }
    return list
  }
  leave = 3 // 控制递归层级
  isall = false // 是否需要全部选项
  constructor({ leave = 0, isall = false }: ChinaAreaInput = {} as ChinaAreaInput) {
    this.leave = leave
    this.isall = isall
    this.chinaAreaflat = this.chinaObj()
  }
  // 省市区数据格式化
  chinaData() {
    const province = chinaAreaData[86]
    const opt: InRecursion = { ssq: province }
    if (this.isall) {
      opt.custom = {
        label: '全部',
        value: 'all',
      }
    }
    return this.recursion(opt)
  }
  // 递归得到省市区三级数据
  private recursion({
    ssq,
    leave = 0, // 这个不是外部操作的,不允许修改
    custom,
  }: InRecursion) {
    const layer = leave + 1
    if (layer > this.leave) return
    const reprovince = []
    custom && reprovince.push(custom)
    for (const i in ssq) {
      const item: Options = {
        label: ssq[i],
        value: i,
        leave: layer,
      }
      if (chinaAreaData[i]) {
        item.children = this.recursion({ ssq: chinaAreaData[i], leave: layer, custom })
      }
      reprovince.push(item)
    }
    return reprovince
  }
}

export default ChinaArea

使用

npm地址:https://www.npmjs.com/package/elui-china-area-dht

git地址:https://github.com/ht-sauce/elui-china-area-dht

语雀说明文档地址:https://www.yuque.com/cv8igf/gaxplg/btzy5i

npm i elui-china-area-dht

代码部分

<template>
  <div class="app">
    <!--默认使用-->
    <elui-china-area-dht @change="onChange"></elui-china-area-dht>
    <!--带isall参数和leave参数示例-->
    <elui-china-area-dht isall :leave="2" @change="onChange"></elui-china-area-dht>
  </div>
</template>

<script>
import { defineComponent } from 'vue'
import { EluiChinaAreaDht } from 'elui-china-area-dht'
const chinaData = new EluiChinaAreaDht.ChinaArea().chinaAreaflat
export default defineComponent({
    components: {
        EluiChinaAreaDht,
    },
    setup() {
        function onChange(e) {
          const one = chinaData[e[0]]
          const two = chinaData[e[1]]
          console.log(one, two)
        }
        return {
            onChange,
        }
    },
})
</script>

致谢

element-plus

vue

数据来源:https://github.com/airyland/china-area-data  

注意掘金的博文也是我写的。非盗版。

掘金地址:https://juejin.cn/post/6914110923179474952#heading-5

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值