更新记录
v1.0.0(2026-04-24)
新版本
平台兼容性
uni-app(3.8.1)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
地区筛选组件使用说明(AreaCascaderPopup)
「地区筛选」的完整接入方式。组件源码:components/area-cascader-popup//area-cascader-popup.vue。
1. 功能说明
在导航栏右侧展示可点击文案(默认「地区筛选」),点击后从底部弹出省 / 市 / 区级联选择器;选择确定后把 省、市、区 ID 传给列表接口;支持 重置 清空条件并刷新列表。地区树数据来自接口 sysAreaOfficeTree,并做 1 分钟本地缓存(uni.setStorageSync('areaData', …))。
2. 引入与注册
import AreaCascaderPopup from 'components/area-cascader-popup/area-cascader-popup.vue';
export default {
components: {
AreaCascaderPopup
},
// ...
};
3. 模板中的用法
与 index.vue 一致:页面根级放置弹层组件,ref 用于调用 open()。
导航栏触发(节选):
<nav-bar slot="top" :title="'XXXX'" :customRight="true">
<template >
<view class="filter-btn" @click="handleFilter">
<text class="filter-text">{{ filterText }}</text>
</view>
</template>
</nav-bar>
弹层组件:
<area-cascader-popup
ref="areaCascader"
:options="cascaderOptions"
placeholder="请选择省市区"
:needLoadData="true"
:maxLevel="3"
@loadData="handleLoadData"
@confirm="handleCascaderConfirm"
@reset="handleResetFilter"
/>
4. 组件 Props
| 属性 | 类型 | 说明 |
|---|---|---|
options |
Array |
级联数据源,节点格式见下文「数据格式」 |
placeholder |
String |
弹层标题文案,示例:请选择省市区 |
needLoadData |
Boolean |
为 true 且打开时 options 为空,会先 loading,并通过 @loadData 把回调交给页面拉数 |
maxLevel |
Number |
最大层级:1 省、2 省市、3 省市区(本页为 3) |
5. 数据格式(options / cascaderOptions)
组件要求每个节点为:
{ id: string | number, name: string, children?: 同结构[] }
本页接口返回为 label + children,通过 convertToXmCascaderFormat 转成 name:
convertToXmCascaderFormat(data) {
if (!data || !Array.isArray(data)) return [];
return data.map(item => {
const result = { id: item.id, name: item.label };
if (item.children && item.children.length > 0) {
result.children = this.convertToXmCascaderFormat(item.children);
}
return result;
});
}
根级列表来自 sysAreaOfficeTree() 的 res.data[0].children(存到 AllAddress 后再转换赋给 cascaderOptions)。
6. 页面侧 data 字段(与筛选联动)
data() {
return {
AllAddress: [], // 原始区划树(接口 children)
cascaderOptions: [], // 传给组件的 options
filterProvinceId: null,
filterCityId: null,
filterAreaId: null,
filterText: '地区筛选', // 导航栏右侧展示文案
};
}
7. 拉取地区数据与缓存
- 缓存键:
areaData,结构含time、areaData。 - 超过 60 秒或无缓存则请求
sysAreaOfficeTree(),否则直接用缓存。 - 拿到数据后调用
initSelect()填充cascaderOptions。
(实现见 index.vue 的 getArea、initSelect。)
8. 事件与 ref 方法
ref 方法
| 方法 | 说明 |
|---|---|
this.$refs.areaCascader.open() |
打开底部弹层;若 needLoadData 且当前无 options,会触发 loadData |
@loadData
组件传入一个 回调函数,页面在异步拉完区划并赋好 cascaderOptions 后 必须调用该回调,以结束 loading 并展示列表。
示例(与 index.vue 一致):
handleLoadData(callback) {
this.getArea()
.then(() => callback())
.catch(() => {
uni.showToast({ title: '数据加载失败', icon: 'none' });
callback();
});
}
@confirm
确认时组件 emit 的 result 结构:
{
selectedId: string | number, // 最后一级选中项 id
selectedPath: Array<{ id, name }>, // 从省到当前级的路径
level: number // 路径长度:1 省 / 2 市 / 3 区
}
本页在 handleCascaderConfirm 中映射为请求参数,并截断按钮文案(最多 4 字 + ...):
handleCascaderConfirm(result) {
if (!result || !result.selectedPath || result.selectedPath.length === 0) {
this.filterProvinceId = null;
this.filterCityId = null;
this.filterAreaId = null;
this.filterText = '地区筛选';
} else {
const path = result.selectedPath;
this.filterProvinceId = path.length >= 1 ? path[0].id : null;
this.filterCityId = path.length >= 2 ? path[1].id : null;
this.filterAreaId = path.length >= 3 ? path[2].id : null;
const lastItem = path[path.length - 1];
const text = lastItem.name || '';
this.filterText = text.length > 4 ? text.substring(0, 4) + '...' : text;
}
this.$refs.paging.reload();
}
@reset
点击弹层内「重置」时触发。本页清空三个 ID 与 filterText,并 reload 列表:
handleResetFilter() {
this.filterProvinceId = null;
this.filterCityId = null;
this.filterAreaId = null;
this.filterText = '地区筛选';
this.$refs.paging.reload();
}
9. 与列表查询参数联动
列表请求里带上区划 ID(空值可从参数中删掉),示例:
let params = {
// ...
provinceId: this.filterProvinceId || null,
cityId: this.filterCityId || null,
areaId: this.filterAreaId || null,
};
Object.keys(params).forEach(key => {
if (params[key] === null) delete params[key];
});
10. 注意事项
needLoadData为true时:首次打开若options为空,依赖loadData里请求完成后callback()被调用,否则一直处于加载中。- 仅选到市或省:
selectedPath长度可能为 1 或 2,本页对cityId/areaId按长度判断赋值,与业务接口约定一致即可。 - 关闭方式:除「确定」「重置」外,用户可点「取消」或关闭图标,此时 不会 触发
confirm,已选状态以组件内部为准;若需「关闭即放弃本次选择」一般无需额外处理(下次open会reset内部状态)。

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 6
赞赏 1
下载 11677742
赞赏 1908
赞赏
京公网安备:11010802035340号