vue利用级联选择器实现全国省市区乡村五级菜单联动

6a044de53fc68f33cb527a15ab4d22e7.png

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。

现在是:2022年2月13日20:09:27

今天分享一个五级级联地址的组件的使用吧。

前言

接到这样的一个需求:需要根据地址查询列表信息,地址可以分别按照省、市、县、乡、村 五级作为条件查询。

如果但是这个需求还好说,以前使用的方式是放五个下拉列表,通过懒加载的方式,根据省得到该省下的市,根据市得到该市下的县……最后可以得到村的级别,然后作为条件查询,也就是下面的这种方式:

b799c108260b577d2b5e61b134308afc.png
image-20220213201630629
a10cb542ab3ce76e329c578ee43c51b5.png
image-20220213201641535

但是,客户说,太长了……因为他的另一个需求是这样的:

74d0dd598b62e0722f6b6a1e1ff323ec.png
image-20220213203322417

如果放5个的话,就会造成装不下的bug。

7b2f16690201a8aa736ae1a831888f6c.png
image-20220213203822894

实现思路

原来采用的是select,现在看来,select显然不是最好的解决方式,去element-ui上面看了看,发现了另一个组件:Cascader 级联选择器,样式如下:

5ba691d630a96624bec622128d28a898.png
image-20220213204120997

于是就把这个Cascader 组件改了改,改成了省市区乡村的组件,同时也做成了公共组件,项目中可以多次共用。

数据表结构

全国省市区乡村没有使用json的方式,将所有的省市区乡村信息都放在了数据库中,用的时候根据父级编号查询,数据库表结构如下:

a125970ad4eec87310240b58aebabfe6.png
image-20220213204531326

级联实现地址联动

实现思路:页面初次加载的时候,将全国所有省查询出来,封装放在级联组件Cascader中,当用户选择某个省的时候,将当前省的编码作为父级编码,去查询所有的市。比如选的山东省,查询出来的就是山东所有市,济南,聊城,菏泽等。

为了解决系统性能问题,我将查询出来的信息都放在了redis缓存中了,缓存里面没有的话去数据库里面找去,有则在缓存中取,效率要高点儿。

下面是公共组件中的代码:

<!--作者:mxx时间:2022年2月11日16:22:07描述:el-Cascader实现省市区乡村菜单
-->
<template><div><div class="block"><el-cascaderv-model="selectedOptions":show-all-levels="false"ref="sysCascader":size="size":placeholder="placeholder":props="props"@change="handleChange"clearable></el-cascader></div><!--  鼠标悬浮触发  -->
<!--    <div class="block"><span class="demonstration">hover 触发子菜单</span><el-cascaderexpand-trigger="hover":options="options"v-model="selectedOptions2"@change="handleChange"></el-cascader></div>--></div>
</template><script>
import {listArea} from "../../../api/system/area";
export default {name: "addressCommonComponentsUtils",props: {//组件大小size: {type: String,default: "mini"},//组件的提示信息placeholder: {type: String,default: "请选择地区"}},data() {let self = this;return {/*省市区的集合*/options: [],props: {lazy: true,checkStrictly: true,lazyLoad: this.getLazyLoad,},selectedOptions: [],// 地址查询参数qParams: {pid: null,type: null,},//省市区的值addressInfo: {//编码//省sonProvinceValue: null,//市sonCityValue: null,//区sonAreaValue: null,//街道sonStreetValue: null,//乡村sonCountryValue: null,//名字//省sonProvinceName: null,//市sonCityName: null,//区sonAreaName: null,//街道sonStreetName: null,//乡村sonCountryName: null,},};},created() {},methods: {//懒加载省份信息到组件中getLazyLoad(node, resolve) {setTimeout(() => {if (node.level == 0) {this.qParams.type = 1;listArea(this.qParams).then(res => {const cities = res.rows.map((value, i) => ({value: value.areaId,label: value.name,leaf: node.level >= 2,}));// 通过调用resolve将子节点数据返回,通知组件数据加载完成resolve(cities);}).catch(err => {console.log(err);});}if (node.level != 0 && node.level < 5) {this.qParams.type = node.level + 1;this.qParams.pid = node.value;listArea(this.qParams).then(res => {const areas = res.rows.map((value, i) => ({value: value.areaId,label: value.name,leaf: node.level >= 4}));//设置省市区街村的值this.setNameAndValue(node);// 通过调用resolve将子节点数据返回,通知组件数据加载完成resolve(areas);}).catch(err => {console.log(err);});} else if (node.level == 5) {//最后一个节点,不去查询了,直接赋值const areas = {value: node.value,label: node.label,leaf: node.level};//将值和名称赋值到变量里面this.addressInfo.sonCountryValue = node.value;this.addressInfo.sonCountryName = node.label;resolve(areas);}}, 10);},//通过当前选择的地区,设置到对应的变量中setNameAndValue(node) {switch (node.level) {case 1:this.addressInfo.sonProvinceValue = node.value;this.addressInfo.sonProvinceName = node.label;this.addressInfo.sonCityValue = null;this.addressInfo.sonCityName = null;this.addressInfo.sonAreaValue = null;this.addressInfo.sonAreaName = null;this.addressInfo.sonStreetValue = null;this.addressInfo.sonStreetName = null;this.addressInfo.sonCountryValue = null;this.addressInfo.sonCountryName = null;break;case 2:this.addressInfo.sonCityValue = node.value;this.addressInfo.sonCityName = node.label;this.addressInfo.sonAreaValue = null;this.addressInfo.sonAreaName = null;this.addressInfo.sonStreetValue = null;this.addressInfo.sonStreetName = null;this.addressInfo.sonCountryValue = null;this.addressInfo.sonCountryName = null;break;case 3:this.addressInfo.sonAreaValue = node.value;this.addressInfo.sonAreaName = node.label;this.addressInfo.sonStreetValue = null;this.addressInfo.sonStreetName = null;this.addressInfo.sonCountryValue = null;this.addressInfo.sonCountryName = null;break;case 4:this.addressInfo.sonStreetValue = node.value;this.addressInfo.sonStreetName = node.label;this.addressInfo.sonCountryValue = null;this.addressInfo.sonCountryName = null;break;case 5:this.addressInfo.sonCountryValue = node.value;this.addressInfo.sonCountryName = node.label;break;}},/*改变事件*/handleChange(event) {let node = this.$refs.sysCascader.getCheckedNodes()[0];//解决不点字  只点击单选按钮的问题this.setNameAndValue(node);//将该组件中的值传递给父组件//getCheckedAddressInfo: 是父组件指定的传数据绑定的函数,this.$emit('getCheckedAddressInfo', this.addressInfo)},}
}
</script><style scoped></style>

关键代码都有相应的注释,应该看起来都没有问题。

或许有些地方的代码冗余,但是我没法再优化了……这个组件大致的功能就是将用户选择的地址信息,传递到父组件中,父组件通过getCheckedAddressInfo函数拿到用户选择的地址信息,不管选择哪一级都可以,最后在根据地址信息做其他操作。

listArea方法:根据条件查询地址信息,传递的参数是地址实体,在本文的最后我附上后台的实现代码。

级联地址组件的使用

使用方法也很简单,只需这么几步:

1.先导入组件:

import addressCommonComponentsUtils from "../area/addressCommonComponentsUtils";

2.注册组件:

export default 里面写如下代码:

components: {"address-utils": addressCommonComponentsUtils,},
70d1cc919e07f6cf43f1311ff59837e2.png
image-20220213212322706

3.在template中引入级联地址组件:

<address-utils:size="mini":placeholder="checkdiqu"@getCheckedAddressInfo="getCheckedAddressInfo"></address-utils>

4.在methods中写getCheckedAddressInfo方法回去选择的地址信息:

//获取用户选择的地址信息getCheckedAddressInfo(value){//给地址栏中赋值this.queryParams.fieldProvince = value.sonProvinceName;this.queryParams.fieldCity = value.sonCityName;this.queryParams.fieldArea = value.sonAreaName;this.queryParams.fieldStreet = value.sonStreetName;this.queryParams.fieldCommunity = value.sonCountryName;},

参数说明:

编码:比如北京是110000,山西是:140000等

  • //省 `sonProvinceValue,

  • //市 `sonCityValue,

  • //区 `sonAreaValue,

  • //街道 `sonStreetValue,

  • //乡村 `sonCountryValue,

名字:比如北京是**【北京】,山西是【山西省】**

  • //省 sonProvinceName,

  • //市 `sonCityName,

  • //区 `sonAreaName,

  • //街道 `sonStreetName,

  • //乡村 sonCountryName,

最后实现的效果如下:

545d0dbecc8cb41f18e0373613da782e.png
image-20220213213301547

附:后台查询地址的代码

area.js:

// 查询地址列表
export function listArea(query) {return request({url: '/system/area/list',method: 'get',params: query})
}

SysAreaController中的代码:

@Autowiredprivate ISysAreaService sysAreaService;/*** 查询地址列表*///@PreAuthorize("@ss.hasPermi('system:area:list')")@GetMapping("/list")public TableDataInfo list(SysArea sysArea){// startPage();List<SysArea> list = sysAreaService.selectSysAreaList(sysArea);return getDataTable(list);}

SysAreaServiceImpl中的代码:

@Autowiredprivate SysAreaMapper sysAreaMapper;@Autowiredprivate RedisCache redisCache;/*** 查询地址* * @param id 地址主键* @return 地址*/@Overridepublic SysArea selectSysAreaById(Long id){return sysAreaMapper.selectSysAreaById(id);}/*** 查询地址列表* * @param sysArea 地址* @return 地址*/@Overridepublic List<SysArea> selectSysAreaList(SysArea sysArea) {//分批次判断地址List<SysArea> areaList = new ArrayList<>();//地址对象SysArea area = new SysArea();if(sysArea.getPid()==null){sysArea.setPid("100000");}//市、区县、街道、村if (redisCache.getCacheList(sysArea.getPid() + "ListCache").size()==0) {System.out.println("=========================走数据库了=========================");area.setType(sysArea.getType());//将父级编号放进来area.setPid(sysArea.getPid());areaList = sysAreaMapper.selectSysAreaList(area);redisCache.setCacheList(sysArea.getPid() + "ListCache", areaList);} else {System.out.println("=========================走缓存了=========================");//从缓存中取出来areaList = redisCache.getCacheList(sysArea.getPid() + "ListCache");}return areaList;}

Mapper层和Service的接口层就不放了,就正常写,返回集合就行:

/*** 查询地址列表* * @param sysArea 地址* @return 地址集合*/public List<SysArea> selectSysAreaList(SysArea sysArea);

最后是mapper.xml中的sql:

<sql id="selectSysAreaVo">select id, name, area_id, pid, type, status, del_flag, create_time, update_time, pids, m_pid, m_pids, m_type, region, remark from sys_area</sql><select id="selectSysAreaList" parameterType="SysArea" resultMap="SysAreaResult"><include refid="selectSysAreaVo"/><where><if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if><if test="areaId != null  and areaId != ''"> and area_id = #{areaId}</if><if test="pid != null  and pid != ''"> and pid = #{pid}</if><if test="type != null "> and type = #{type}</if><if test="status != null "> and status = #{status}</if><if test="pids != null  and pids != ''"> and pids = #{pids}</if><if test="mPid != null  and mPid != ''"> and m_pid = #{mPid}</if><if test="mPids != null  and mPids != ''"> and m_pids = #{mPids}</if><if test="mType != null "> and m_type = #{mType}</if><if test="region != null  and region != ''"> and region = #{region}</if></where></select>

总结

好了,今天分享的就这些了,源码也都贴上来啦,记录记录,一来或许可以帮助大家,二来自己以后用的时候,也可以直接上来扒代码了。

下一篇:springboot解析word文档,包括复杂的图片,复选框等。

问:你知道CV工程师是啥吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323725.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

业务库负载翻了百倍,我做了什么来拯救MySQL架构

转载自 业务库负载翻了百倍&#xff0c;我做了什么来拯救MySQL架构 作者介绍 杨建荣&#xff0c;竞技世界资深DBA&#xff0c;前搜狐畅游数据库专家&#xff0c;Oracle ACE&#xff0c;YEP成员。拥有近十年数据库开发和运维经验&#xff0c;目前专注于开源技术、运维自动化和…

ASP.NET Core 运行原理解剖[4]:进入HttpContext的世界

本系列文章从源码分析的角度来探索 ASP.NET Core 的运行原理&#xff0c;分为以下几个章节&#xff1a; ASP.NET Core 运行原理解剖[1]:Hosting ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍 ASP.NET Core 运行原理解剖[3]:Middleware-请求管道的构成 IHttpContext…

都忘了自己还有一套房子了。。。

​自20年始来&#xff0c;一直租着我的房子。当时疫情刚刚有所好转&#xff0c;我把房子挂在58上&#xff0c;陆陆续续的有好多人问&#xff0c;不过都没有租&#xff0c;一来离我住的地方有点远&#xff0c;过去一次得个把小时的&#xff0c;人家要看房子不能及时过去。二来问…

Visual Studio2017 远程调试 Remote Debugger

前言 大家在使用vs打包后的文件部署到服务器后&#xff0c;有时候我们需要对线网的后台进行调试。但是它不像在VS中。这个时候我们该怎么调试呢&#xff1f; 微软想到了这一点&#xff0c;他们在 VS 中给我们提供了一个功能: Remote Debugger&#xff0c;要远程调试我们就需要…

对于这款APP,我充了个终身VIP!!!

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。”现在是&#xff1a;2022年3月15日00:02:07昨天&#xff0c;无意间知道了一款特牛的APP&#xff0c;看了看&#xff0c;决定充了个终身会员&#xff01;今天&#xff0c;我就简单的对这…

Ubuntu amp;amp; GitLab CI amp;amp; Docker amp;amp; ASP.NETnbs

上一篇&#xff1a;Ubuntu & GitLab CI & Docker & ASP.NET Core 2.0 自动化发布和部署&#xff08;1&#xff09; 服务器版本 Ubuntu 16.04 LTS。 本篇博文目的&#xff1a;项目中添加Dockerfile文件&#xff0c;使用 CI 脚本构建自定义镜像&#xff0c;推送到 …

新版《Windows Sysinternals实战指南》,读书积赞活动

新书《Windows Sysinternals实战指南》即将上市。该本由Sysinternals创始人、Windwos内核技术专家Mark Russinovich 与 Windows专家Aaron Margosis联手编著&#xff0c;详细介绍了Sysinternals每款工具的独到功能&#xff0c;并用较多篇幅深入介绍了如何通过几款重量级工具优化…

Bladex生成Swagger的方法

一、在启动类中添加如下代码&#xff1a;&#xff08;目的是为了打印输出swagger的地址等&#xff09; 注解&#xff1a;Slf4j 实现接口&#xff1a;CommandLineRunner 依赖注入&#xff1a; Autowiredprivate Environment environment;Overridepublic void run(String... str…

了解spark计算模型

简介 在集群背后&#xff0c;有一个非常重要的分布式数据架构&#xff0c;即弹性分布式数据集&#xff08;resilient distributed dataset&#xff0c;RDD&#xff09;&#xff0c;它是逻辑集中的实体&#xff0c;在集群中的多台机器上进行了数据分区。通过对多台机器上不同RDD…

如何理解事件溯源

在近期举行的PHPDublin见面会上&#xff0c;来自DynamicRes的架构师Barry Sullivan被问到“什么是事件溯源”&#xff0c;作为对这个问题的回答&#xff0c;他在博客上写下了这篇文章&#xff0c;详细解释了什么是事件溯源以及事件溯源有哪些好处。以下内容翻译自Barry的博客&a…

java中日期处理的一些工具方法

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年4月16日15:35:14&#xff01;忙里偷闲&#xff0c;直接来看方法吧&#xff0c;写完文章继续去改Bug: 1.计算两个日期之间相差的天数 /*** param stratTime 开始时间* p…

ASP.NET Core 运行原理解剖[5]:Authentication

在现代应用程序中&#xff0c;认证已不再是简单的将用户凭证保存在浏览器中&#xff0c;而要适应多种场景&#xff0c;如App&#xff0c;WebAPI&#xff0c;第三方登录等等。在 ASP.NET 4.x 时代的Windows认证和Forms认证已无法满足现代化的需求&#xff0c;因此在ASP.NET Core…

bladex自定义分页

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年4月16日21:44:05&#xff01;今天分享一个代码段&#xff0c;个人觉得还是比较有参考性的。 后端使用框架&#xff1a;bladex前端使用技术&#xff1a;AVue功能:自定义分…

bladex中自定义分页的写法~

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是2022年4月16日21:44:05&#xff01;今天分享一个代码段&#xff0c;个人觉得还是比较有参考性的。后端使用框架&#xff1a;bladex前端使用技术&#xff1a;AVue功能:自定义分…

OpenID Connect:OAuth 2.0协议之上的简单身份层

OpenID Connect是什么&#xff1f;OpenID Connect(目前版本是1.0)是OAuth 2.0协议(可参考本人此篇&#xff1a;OAuth 2.0 / RCF6749 协议解读)之上的简单身份层&#xff0c;用 API 进行身份交互的框架&#xff0c;允许客户端根据授权服务器的认证结果最终确认用户的身份&#x…

一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系

我们知道&#xff0c;不同肤色的人外貌差别很大&#xff0c;而双胞胎的辨识很难。有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎&#xff0c;在网络上经常一起出现。本文将带读者对这四个相似概念如何区分。 1.1. Web服务器概念与基本原理 1.1.1. Web服…

bladex实现单点登录

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年4月17日16:19:51 在实际开发中&#xff0c;有时候我们有这样的需求&#xff0c;即&#xff0c;一个体系中的用户是共通的&#xff0c;比如统一体系下&#…

若依实现单点登录(解析请求链接中的参数做鉴权认证)

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年4月19日19:56:56 昨天写了个bladex的单点登录&#xff0c;回想起来还是比较复杂的&#xff0c;今天又收到了个在若依里面实现单点登录。具体是这样的:别的系…

Docker打包 Asp.Net Core应用,在CentOS上运行

本文主要介绍下运用docker虚拟技术打包Asp.net core应用。 Docker作为一个开源的应用容器引擎&#xff0c;近几年得到广泛的应用&#xff0c;使用Docker我们可以轻松实现应用的持续集成部署&#xff0c;一次打包&#xff0c;到处运行。 开篇借用百科上对docker的介绍。 Docker …

若依实现系统单点登录(可绕过验证码)

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是&#xff1a;2022年4月19日19:56:56昨天写了个bladex的单点登录&#xff0c;回想起来还是比较复杂的&#xff0c;今天又收到了个在若依里面实现单点登录。具体是这样的:别的系…