更新记录

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,结构含 timeareaData
  • 超过 60 秒或无缓存则请求 sysAreaOfficeTree(),否则直接用缓存。
  • 拿到数据后调用 initSelect() 填充 cascaderOptions

(实现见 index.vuegetAreainitSelect。)


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

确认时组件 emitresult 结构:

{
  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. 注意事项

  1. needLoadDatatrue:首次打开若 options 为空,依赖 loadData 里请求完成后 callback() 被调用,否则一直处于加载中。
  2. 仅选到市或省selectedPath 长度可能为 1 或 2,本页对 cityId / areaId 按长度判断赋值,与业务接口约定一致即可。
  3. 关闭方式:除「确定」「重置」外,用户可点「取消」或关闭图标,此时 不会 触发 confirm,已选状态以组件内部为准;若需「关闭即放弃本次选择」一般无需额外处理(下次 openreset 内部状态)。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。