Skip to content

RegionPicker 地区选择器

省市区三级联动选择器组件,支持多种数据格式和显示模式。

基础用法

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const region = ref('')
</script>

<template>
  <RegionPicker v-model="region" />
</template>

三级联动

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const region = ref('')
</script>

<template>
  <RegionPicker 
    v-model="region"
    :level="3"
  />
</template>

返回完整路径

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const region = ref([])
</script>

<template>
  <RegionPicker 
    v-model="region"
    :level="3"
    return-path
  />
  
  <div style="margin-top: 16px">
    选中的地区:{{ region }}
  </div>
</template>

自定义分隔符

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const region = ref('')
</script>

<template>
  <RegionPicker 
    v-model="region"
    :level="3"
    separator=" / "
  />
</template>

API

Props

参数说明类型默认值
modelValue绑定值string | string[]-
level级别(1-省,2-市,3-区)1 | 2 | 33
placeholder占位文本string | string[]['请选择省', '请选择市', '请选择区']
disabled是否禁用booleanfalse
clearable是否可清空booleantrue
separator分隔符string'-'
returnPath是否返回完整路径booleanfalse
data自定义数据源array内置数据

Events

事件名说明回调参数
update:modelValue值变化时触发(value: string | string[]) => void
change值变化时触发(value: string | string[], labels: string[]) => void

Methods

方法名说明参数
clear清空选择-
getLabels获取选中的标签-

完整示例

vue
<script setup lang="ts">
import { ref } from 'vue'
import { message } from 'ant-design-vue'
import { RegionPicker } from '@vben/common-ui'

const region1 = ref('')
const region2 = ref([])
const region3 = ref('')

const handleChange = (value: any, labels: string[]) => {
  console.log('选中的值:', value)
  console.log('选中的标签:', labels)
  message.success(`已选择:${labels.join(' / ')}`)
}
</script>

<template>
  <div class="region-demo">
    <a-space direction="vertical" :size="16" style="width: 100%">
      <!-- 基础用法 -->
      <div>
        <h4>基础用法</h4>
        <RegionPicker 
          v-model="region1"
          :level="3"
          @change="handleChange"
        />
        <div class="result">选中的地区:{{ region1 }}</div>
      </div>
      
      <!-- 返回完整路径 -->
      <div>
        <h4>返回完整路径</h4>
        <RegionPicker 
          v-model="region2"
          :level="3"
          return-path
          @change="handleChange"
        />
        <div class="result">选中的地区:{{ region2 }}</div>
      </div>
      
      <!-- 自定义分隔符 -->
      <div>
        <h4>自定义分隔符</h4>
        <RegionPicker 
          v-model="region3"
          :level="3"
          separator=" > "
          @change="handleChange"
        />
        <div class="result">选中的地区:{{ region3 }}</div>
      </div>
    </a-space>
  </div>
</template>

<style scoped>
.region-demo h4 {
  margin-bottom: 8px;
  font-weight: 600;
}

.result {
  margin-top: 8px;
  padding: 8px 12px;
  background: #f5f5f5;
  border-radius: 4px;
  font-size: 14px;
  color: #666;
}
</style>

表单集成

vue
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { Form, FormItem, Button } from 'ant-design-vue'
import { RegionPicker } from '@vben/common-ui'

const formRef = ref()
const formData = reactive({
  name: '',
  region: '',
  address: ''
})

const rules = {
  name: [{ required: true, message: '请输入姓名' }],
  region: [{ required: true, message: '请选择地区' }],
  address: [{ required: true, message: '请输入详细地址' }]
}

const handleSubmit = async () => {
  await formRef.value?.validate()
  console.log('提交数据:', formData)
}
</script>

<template>
  <Form
    ref="formRef"
    :model="formData"
    :rules="rules"
    :label-col="{ span: 6 }"
    :wrapper-col="{ span: 18 }"
  >
    <FormItem label="姓名" name="name">
      <a-input v-model:value="formData.name" />
    </FormItem>
    
    <FormItem label="所在地区" name="region">
      <RegionPicker 
        v-model="formData.region"
        :level="3"
      />
    </FormItem>
    
    <FormItem label="详细地址" name="address">
      <a-textarea 
        v-model:value="formData.address"
        :rows="3"
      />
    </FormItem>
    
    <FormItem :wrapper-col="{ offset: 6 }">
      <a-space>
        <Button type="primary" @click="handleSubmit">提交</Button>
        <Button @click="formRef?.resetFields()">重置</Button>
      </a-space>
    </FormItem>
  </Form>
</template>

自定义数据源

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const region = ref('')

// 自定义数据源
const customData = [
  {
    value: '110000',
    label: '北京市',
    children: [
      {
        value: '110100',
        label: '北京市',
        children: [
          { value: '110101', label: '东城区' },
          { value: '110102', label: '西城区' },
          { value: '110105', label: '朝阳区' },
          { value: '110106', label: '丰台区' }
        ]
      }
    ]
  },
  {
    value: '310000',
    label: '上海市',
    children: [
      {
        value: '310100',
        label: '上海市',
        children: [
          { value: '310101', label: '黄浦区' },
          { value: '310104', label: '徐汇区' },
          { value: '310105', label: '长宁区' },
          { value: '310106', label: '静安区' }
        ]
      }
    ]
  }
]
</script>

<template>
  <RegionPicker 
    v-model="region"
    :level="3"
    :data="customData"
  />
</template>

动态加载

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'
import axios from 'axios'

const region = ref('')

// 动态加载数据
const loadData = async (level: number, parentCode?: string) => {
  const { data } = await axios.get('/api/region/list', {
    params: { level, parentCode }
  })
  return data
}
</script>

<template>
  <RegionPicker 
    v-model="region"
    :level="3"
    :load-data="loadData"
  />
</template>

只选择省份

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const province = ref('')
</script>

<template>
  <RegionPicker 
    v-model="province"
    :level="1"
    placeholder="请选择省份"
  />
</template>

只选择省市

vue
<script setup lang="ts">
import { ref } from 'vue'
import { RegionPicker } from '@vben/common-ui'

const city = ref('')
</script>

<template>
  <RegionPicker 
    v-model="city"
    :level="2"
    :placeholder="['请选择省份', '请选择城市']"
  />
</template>

数据格式

内置数据格式

typescript
interface RegionData {
  value: string      // 地区代码
  label: string      // 地区名称
  children?: RegionData[]  // 子地区
}

示例数据

json
[
  {
    "value": "110000",
    "label": "北京市",
    "children": [
      {
        "value": "110100",
        "label": "北京市",
        "children": [
          { "value": "110101", "label": "东城区" },
          { "value": "110102", "label": "西城区" }
        ]
      }
    ]
  }
]

返回值格式

默认格式(字符串)

typescript
// level = 3, separator = '-'
"110000-110100-110101"  // 北京市-北京市-东城区

完整路径(数组)

typescript
// level = 3, returnPath = true
["110000", "110100", "110101"]

样式定制

vue
<style>
/* 自定义选择器样式 */
.region-picker {
  width: 100%;
}

.region-picker .ant-select {
  width: 100%;
}

/* 自定义下拉菜单样式 */
.region-picker-dropdown {
  max-height: 300px;
}

.region-picker-dropdown .ant-select-item {
  padding: 8px 12px;
}
</style>

注意事项

注意

  1. 地区数据需要定期更新,确保数据准确性
  2. 大数据量时建议使用动态加载
  3. 返回值格式要与后端约定一致
  4. 注意处理数据为空的情况

提示

  • 使用 returnPath 返回完整路径数组
  • 可以通过 data 属性自定义数据源
  • 支持动态加载数据
  • 使用 separator 自定义分隔符
  • 支持 1-3 级联动选择

相关链接

MIT License