在 UniApp 中使用 uni-data-picker 实现省市区地址选择
一、需求分析与技术准备
1. 核心需求
-
点击地址输入框弹出省市区三级选择器 -
选择后,将省市区名称与编码回显到输入框,并存储到表单对象 -
支持输入框清空功能
2. 技术依赖
-
UniApp 框架 uni-data-picker 扩展组件(需在 HBuilderX 中导入) -
后端提供省市区树形结构数据接口 -
Redis 缓存(后端用于优化数据查询性能)
二、实现步骤
1. 后端接口准备
/*** 获取省市区树形列表* @return void*/public functiontreeList(){$key = 'area_tree_list';$list = redis_utils()->get($key);// 缓存不存在则从数据库查询并构建树形结构if (!$list) {$list = \app\common\model\Area::field('id,pid,name')->order('id asc')->select()->toArray();$tree = new Tree();$list = $tree->list_to_tree($list, 'id', 'pid', 'children');// 缓存1小时redis_utils()->set($key, $list, 3600);}$this->success('成功', $list);}
{"id": 1,"pid": 0,"name": "北京","children": [{"id": 2,"pid": 1,"name": "北京市","children": [{"id": 3,"pid": 2,"name": "东城区"}// 其他区县...]}]}
2. 前端页面布局
<template><viewclass="form-container"><!-- 地址选择项 --><viewclass="item flex-row" @click="selectArea"><textclass="label">地址</text><uv-inputv-model="areaText"border="none"clearableplaceholder="省、市、区、街道"placeholder-class="placeholder-class"/></view><!-- 省市区选择器 --><viewstyle="position: relative"><uni-data-pickerv-if="openPicker"ref="areaPicker"v-model="formData.areas"placeholder="请选择地址"popup-title="请选择城市":localdata="areaList":map="{text:'name',value:'id'}"self-field="id"parent-field="pid"@change="onchange"/><!-- 遮罩层:防止选择器未激活时被点击 --><viewstyle="position: absolute;background-color: #F5F5F5;width: 100%;height: 90rpx;left: 0;top: 0" /></view></view></template>
3. 样式美化
<stylescoped>.item {padding: 40rpx 0;border-bottom: 1rpx solid #F8F9FA;/* 占位符样式 */.placeholder-class {color: #999999;font-size: 26rpx;}/* 标签样式 */.label {font-size: 30rpx;width: 140rpx;font-weight: 400;}}</style>
4. 逻辑实现
<script>export default {data() {return {// 地址输入框显示文本areaText: '',// 选择器显示状态openPicker: true,// 省市区树形数据areaList: [],// 表单数据formData: {areas: [],province: '',city: '',area: '',province_code: '',city_code: '',area_code: ''}}},onLoad() {// 页面加载时请求省市区数据this.getAreaList();},methods: {/*** 请求省市区树形数据*/getAreaList() {api.area.treeList().then(res => {this.areaList = res.data})},/*** 点击地址项打开选择器*/selectArea() {this.$refs.areaPicker.show();},/*** 选择器值改变事件* @param {Object} e - 事件对象*/onchange(e) {const value = e.detail.value;// 存储省市区名称和编码this.formData.province = value[0].text;this.formData.city = value[1].text;this.formData.area = value[2].text;this.formData.province_code = value[0].value;this.formData.city_code = value[1].value;this.formData.area_code = value[2].value;// 回显到输入框this.areaText = `${value[0].text}/${value[1].text}/${value[2].text}`;}}}</script>
三、关键配置说明
1. uni-data-picker 核心属性
-
localdata:绑定省市区树形数据,是实现三级联动的核心数据源 -
map:映射数据字段,{text:’name’,value:’id’} 表示将数据中的 name 作为显示文本,id 作为值 -
self-field:当前节点 ID 字段名,对应数据中的 id -
parent-field:父节点 ID 字段名,对应数据中的 pid -
v-model:绑定选中的地址数据数组
2. 交互逻辑
四、优化建议
1. 性能优化
-
后端通过 Redis 缓存省市区数据,避免频繁查询数据库 -
前端可对省市区数据做本地缓存,避免重复请求接口
2. 体验优化
-
添加加载状态,请求数据时显示加载动画 -
处理选择器数据为空的异常情况 -
支持地址输入框手动输入,结合选择器使用 -
增加省份快速定位功能,提升选择效率
3. 兼容性优化
-
适配不同端(微信小程序、App、H5)的样式和交互差异 -
处理部分地区只有两级数据的情况(如直辖市)
总结
-
使用 uni-data-picker 实现地址选择的核心是正确配置树形数据和字段映射,localdata、map、self-field、parent-field 是关键属性。 -
交互逻辑上,通过控制选择器的显示隐藏,结合 change 事件处理选中数据,实现输入框回显和表单数据存储。 -
前后端配合优化(如 Redis 缓存、异常处理)能大幅提升地址选择功能的性能和用户体验。


夜雨聆风
