300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > vue利用级联选择器实现全国省市区乡村五级菜单联动

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

时间:2020-02-12 04:21:19

相关推荐

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

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

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

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

前言

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

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

image-30629
image-41535

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

image-203322417

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

image-203822894

实现思路

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

image-204120997

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

数据表结构

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

image-204531326

级联实现地址联动

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

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

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

<!--作者:mxx时间: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.先导入组件:

importaddressCommonComponentsUtilsfrom"../area/addressCommonComponentsUtils";

2.注册组件:

export default里面写如下代码:

components:{"address-utils":addressCommonComponentsUtils,},

image-212322706

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,

最后实现的效果如下:

image-213301547

附:后台查询地址的代码

area.js:

//查询地址列表exportfunctionlistArea(query){returnrequest({url:'/system/area/list',method:'get',params:query})}

SysAreaController中的代码:

@AutowiredprivateISysAreaServicesysAreaService;/***查询地址列表*///@PreAuthorize("@ss.hasPermi('system:area:list')")@GetMapping("/list")publicTableDataInfolist(SysAreasysArea){//startPage();List<SysArea>list=sysAreaService.selectSysAreaList(sysArea);returngetDataTable(list);}

SysAreaServiceImpl中的代码:

@AutowiredprivateSysAreaMappersysAreaMapper;@AutowiredprivateRedisCacheredisCache;/***查询地址**@paramid地址主键*@return地址*/@OverridepublicSysAreaselectSysAreaById(Longid){returnsysAreaMapper.selectSysAreaById(id);}/***查询地址列表**@paramsysArea地址*@return地址*/@OverridepublicList<SysArea>selectSysAreaList(SysAreasysArea){//分批次判断地址List<SysArea>areaList=newArrayList<>();//地址对象SysAreaarea=newSysArea();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");}returnareaList;}

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

/***查询地址列表**@paramsysArea地址*@return地址集合*/publicList<SysArea>selectSysAreaList(SysAreasysArea);

最后是mapper.xml中的sql:

<sqlid="selectSysAreaVo">selectid,name,area_id,pid,type,status,del_flag,create_time,update_time,pids,m_pid,m_pids,m_type,region,remarkfromsys_area</sql><selectid="selectSysAreaList"parameterType="SysArea"resultMap="SysAreaResult"><includerefid="selectSysAreaVo"/><where><iftest="name!=nullandname!=''">andnamelikeconcat('%',#{name},'%')</if><iftest="areaId!=nullandareaId!=''">andarea_id=#{areaId}</if><iftest="pid!=nullandpid!=''">andpid=#{pid}</if><iftest="type!=null">andtype=#{type}</if><iftest="status!=null">andstatus=#{status}</if><iftest="pids!=nullandpids!=''">andpids=#{pids}</if><iftest="mPid!=nullandmPid!=''">andm_pid=#{mPid}</if><iftest="mPids!=nullandmPids!=''">andm_pids=#{mPids}</if><iftest="mType!=null">andm_type=#{mType}</if><iftest="region!=nullandregion!=''">andregion=#{region}</if></where></select>

总结

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

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。