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 | 3 | 3 |
| placeholder | 占位文本 | string | string[] | ['请选择省', '请选择市', '请选择区'] |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否可清空 | boolean | true |
| separator | 分隔符 | string | '-' |
| returnPath | 是否返回完整路径 | boolean | false |
| 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>注意事项
注意
- 地区数据需要定期更新,确保数据准确性
- 大数据量时建议使用动态加载
- 返回值格式要与后端约定一致
- 注意处理数据为空的情况
提示
- 使用
returnPath返回完整路径数组 - 可以通过
data属性自定义数据源 - 支持动态加载数据
- 使用
separator自定义分隔符 - 支持 1-3 级联动选择