uniapp-地区的四级联动

news2024/11/23 12:13:10

本来填写订单的页面选地址是三级联动的

但是由于领导的要求,需要改成四级联动

解决思路

最开始用的是官方的 picker , 所以我去翻看了uniapp 的官网

我们需要用到的是多列模式

解决步骤

1. 先封装对应的请求

/**
 *   获取省市县街道的列表
 */
export const getAddressList = (data) => request({url: '/system/region/list', method: 'get', data: data })

2. 在data内去定义对应的数据

3. 在页面的 created 钩子函数内去调用方法

data () {
  return {
    provinceList: [], // 地区列表
    province: [], //省数组
    city: [], //市数组
    district: [], //区数组
    street: [], //街道数组
    mulSelect: [], //四级联动显示数组,该数组的值为[[province],[city],[district],[street]]
    mulSelectId: [] ,// 四级联动的id
    provinceId: 110000, //省的id
    cityId: 110101, //市的id
    districtId: 110101001,//区的id
    streetId: '', // 镇/街道id
    address:''
  };
},
created() {
		this.getList('', '1')	
},
methods: {
	// 获取地址列表
  async getList(id, level) {
    const data = {
      parentId: id,
      level: level
    }
    const res = await getAddressList(data)
    if (this.mulSelect.length !== 4) {
      if(level == 1) {
        this.province = res.data.data
        this.getProvince();
        this.mulSelectId.push(res.data.data[0].id)
        this.mulSelect.push(this.province);			
        this.getList(this.provinceId, '2')
      } else if (level == 2) {
        this.city = res.data.data
        this.getCity();
        this.mulSelectId.push(res.data.data[0].id)
        this.mulSelect.push(this.city);
        this.getList(this.cityId, '3')
      } else if (level == 3) {
        this.district = res.data.data
        this.getDistrict();
        this.mulSelectId.push(res.data.data[0].id)
        this.mulSelect.push(this.district);
        this.getList(this.districtId, '4')
      }
    } else {
      if(level == 1) {
        // this.provinceId = res.data.data[0].id
        console.log(id)
        this.mulSelectId[0] = id
        console.log(this.mulSelectId)
        this.getProvince();			
        this.getList(this.provinceId, '2')
      } else if (level == 2) {
        this.city = res.data.data
        this.cityId = res.data.data[0].id
        this.mulSelectId[1] = this.cityId
        this.getCity();
        this.mulSelect[1] = this.city;
        this.getList(this.cityId, '3')
      } else if (level == 3) {
        this.district = res.data.data
        this.districtId = res.data.data[0].id
        this.mulSelectId[2] = this.districtId
        this.getDistrict();
        this.mulSelect[2] = this.district;
        this.getList(this.districtId, '4')
      } else if (level == 4) {
        this.street = res.data.data
        this.streetId = res.data.data[0].id
        this.mulSelectId[3] = this.streetId
        this.getStreet();
        this.mulSelect[3] = this.street;
      }
    }
  },
}

因为这个接口需要两个参数 而第一层级的省份是不需要id,只需要层级 所以在created内去调用的时候 只用传一个参数

这个方法是分了两种情况

第一种情况是刚进入页面的时候去获取地区的时候 因为我们定义的列表 mulSelect 数据是空的,所以说,这个时候 发请求获取到的数据 就是向这个数组内去push

第二种情况是 当后续切换地区的时候 这个时候就不能用push了 只能对应的地方去替换原来的数据

例如: this.mulSelectId[1] = this.cityId

判断条件的话 我预想的比较好的方法就是通过去判断 mulSelect 数组的长度 因为最开始添加的时候length肯定是为0 的 但是这个时候就需要做一个小改动 因为不能直接写

if (this.mulSelect.length == 0) 一些特殊情况 例如北京市 的情况下 总共是只有三级的 然后切换到xx省之后 就有四层数据 这个时候第四层数据怎么去替换呢 只能说push进去

当然 这个方法是接收两个参数的 第一个是对应的id 第二个是层级

因为我们发请求的时候是需要判断层级的 所以我又加了一层if判断 目的是为了区分一下

4. 初次调用请求方法

在实际开发中,为了用户的体验效果 肯定是第一次把四级的数据都展示出来,但是一次只能发一次请求

这个时候层级就派上用场了 当为第一层的时候发第一个请求, 得到省级别的列表,先调另外的方法把列表添加进入 muSelect 数组内

请求成功的时候也是拿到了第一个省份的id,我们拿到id后 递归 调用自身 但是传层级为2和对应的省id,这个时候就进入到了层级为2的逻辑内了 其实和层级1一样 这一层级也是获取到对应的市列表,调用方法添加到数组内 ,然后再调用自身传递3 ...........依次循环,直到循环完四次循环

下面是图解

因为默认第一个北京 只有三层 所以写三层就够了

5. 切换时请求

切换时 绑定的事件 @columnchange="colChange"

// 地址改变触发
		colChange(e) {
			// console.log(e.detail);
			// console.log(this.mulSelect[0][e.detail.value])
			switch (e.detail.column){
				case 0://选择省
					this.mulSelect[1] =[]
					this.mulSelect[2] =[]
					this.mulSelect[3] =[]
					this.provinceId=this.mulSelect[0][e.detail.value].id;
					console.log(this.provinceId)
					this.getList(this.provinceId, e.detail.column+2 )
					
					break;
				case 1://选择市
					this.mulSelect[2] =[]
					this.mulSelect[3] =[]
					this.cityId = this.mulSelect[1][e.detail.value].id;
					this.getList(this.cityId, e.detail.column+2 )
					
					break;
				case 2://选择区
					this.mulSelect[3] =[]
					this.districtId = this.mulSelect[2][e.detail.value].id;
					this.getList(this.districtId, e.detail.column+2 )
					
					break;
				case 3://选择街道
					this.streetId = this.mulSelect[3][e.detail.value].id
					break;
				default:
					break;
			}
		},

触发该事件 事件的e内有一个 detail 里面有两个属性 一个是value 一个是column

value 是对应的层级下的索引

column 是对应的层级

我这里+2 是因为 1. 此处的层级也为索引 是从0开始的,而请求时是从1开始的

2. 得到第一层的id 应该去请求的是第二层的数据 所以还要+1

所以此处的处理逻辑和3差不多,只是多了一个切换 在对应的层级调用对应的接口

请求后的操作也有所区别 ,例如请求得到的数据是直接去赋值替换 不是push添加

再细节一点的地方就是: 发请求前 先把对应需要替换的值先赋值一个空值

6. 完整代码

// 1
<template>
  <view class="input-wrapper">
    <view class="label">所属区县</view>
    <view class="input-box">
      <picker class="input" mode="multiSelector"  :range="mulSelect" :range-key="'fullname'" @change="pickerChange" @columnchange="colChange">
          <view class="region" :class="!address? 'placeholder' : ''">{{address || '请选择区域' }}</view>
      </picker>
    </view>
    <view class="iconfont location" @click="handleLocation">定位</view>
  </view>
</template>

// 2
<script>
	import { getAddressList} from '@/api/add-house/add-house.js'
	export default {
  	data () {
  		return {
  			provinceList: [], // 地区列表
  			province: [], //省数组
  			city: [], //市数组
  			district: [], //区数组
  			street: [], //街道数组
  			mulSelect: [], //四级联动显示数组,该数组的值为[[province],[city],[district],[street]]
  			mulSelectId: [] ,// 四级联动的id
  			provinceId: 110000, //省的id
  			cityId: 110101, //市的id
  			districtId: 110101001,//区的id
  			streetId: '', // 镇/街道id
  			address:''
  		};
  	},
    created() {
  		this.getList('', '1')	
  	},
    methods: {
		// 获取地址列表
		async getList(id, level) {
			const data = {
				parentId: id,
				level: level
			}
			const res = await getAddressList(data)
			if (this.mulSelect.length !== 4) {
				if(level == 1) {
					this.province = res.data.data
					this.mulSelectId.push(res.data.data[0].id)
					this.mulSelect.push(this.province);			
					this.getList(this.provinceId, '2')
				} else if (level == 2) {
					this.city = res.data.data
					this.mulSelectId.push(res.data.data[0].id)
					this.mulSelect.push(this.city);
					this.getList(this.cityId, '3')
				} else if (level == 3) {
					this.district = res.data.data
					this.mulSelectId.push(res.data.data[0].id)
					this.mulSelect.push(this.district);
					this.getList(this.districtId, '4')
				}
				// } else if (level == 4) {
				// 	this.street = res.data.data
				// 	this.mulSelectId.push(res.data.data[0].id)
				// 	this.mulSelect.push(this.street);
				// }
			} else {
				if(level == 1) {
					this.mulSelectId[0] = id		
					this.getList(this.provinceId, '2')
				} else if (level == 2) {
					this.city = res.data.data
					this.cityId = res.data.data[0].id
					this.mulSelectId[0] = id
					this.mulSelect[1] = this.city;
					this.getList(this.cityId, '3')
				} else if (level == 3) {
					this.district = res.data.data
					this.districtId = res.data.data[0].id
					this.mulSelectId[1] = id
					this.mulSelect[2] = this.district;
					this.getList(this.districtId, '4')
				} else if (level == 4) {
					this.street = res.data.data
					this.streetId = res.data.data[0].id
					this.mulSelectId[2] = id
					this.mulSelectId[3] = this.streetId
					console.log(this.mulSelectId)
					this.mulSelect[3] = this.street;
				}
			}
		},
    // 选中的地址发生改变时触发
		pickerChange(e) {
			console.log(e,'change')
			//什么都不选的话,e.detail.value的值为[null,null,null,null]
			//只选择省的话,e.detail.value的值为[数字,null,null,null]
			//只选择市的话,e.detail.value的值为[数字,数字,null,null]
			//所以获取e.detail.value的值先判断是否为null,如果为null则取值为0
			for(var i=0;i<e.detail.value.length;i++){
				if(e.detail.value[i]===null){
					e.detail.value[i]=0;
				}
			}
			
			var s_province=this.mulSelect[0][e.detail.value[0]];//获取选中的省
			var s_city=this.mulSelect[1][e.detail.value[1]||0];//获取选中的市
			var s_district=this.mulSelect[2][e.detail.value[2]||0];//获取选中的区
			if(this.mulSelect[3].length !== 0) {
				console.log(this.mulSelect)
				var s_street=this.mulSelect[3][e.detail.value[3]||0];//获取选中的街
				this.address=s_province.fullname+s_city.fullname+s_district.fullname+s_street.fullname;
			} else {
				this.address=s_province.fullname+s_city.fullname+s_district.fullname
			}

			//赋值显示在页面
		},
		// 地址改变触发
		colChange(e) {
			// console.log(e.detail);
			// console.log(this.mulSelect[0][e.detail.value])
			switch (e.detail.column){
				case 0://选择省
					this.mulSelect[1] =[]
					this.mulSelect[2] =[]
					this.mulSelect[3] =[]
					this.provinceId=this.mulSelect[0][e.detail.value].id;
					console.log(this.provinceId)
					this.getList(this.provinceId, e.detail.column+2 )
					
					break;
				case 1://选择市
					this.mulSelect[2] =[]
					this.mulSelect[3] =[]
					this.cityId = this.mulSelect[1][e.detail.value].id;
					this.getList(this.cityId, e.detail.column+2 )
					
					break;
				case 2://选择区
					this.mulSelect[3] =[]
					this.districtId = this.mulSelect[2][e.detail.value].id;
					this.getList(this.districtId, e.detail.column+2 )
					
					break;
				case 3://选择街道
					this.streetId = this.mulSelect[3][e.detail.value].id
					break;
				default:
					break;
			}
		},
  }
</script>

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

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

相关文章

电脑和手机查看ip地址

文章目录 看电脑 ip 地址查看手机 ip 地址浏览器访问网址获取ip&#xff08;电脑和手机都能用&#xff09; 看电脑 ip 地址 【方法一】 1、电脑右下角找到连接的网络 2、拉到最下面属性即可看到 IP 地址 在这里插入图片描述 【方法二】 1、Win R 然后输入 cmd 打开命令行 …

Springboot后端跨域处理

跨域 当一台服务器资源从另一台服务器&#xff08;不同的域名或者端口&#xff09;请求一个资源或者接口&#xff0c;就会发起一个跨域HTTP请求。 同源&#xff1a;协议、域名、端口都相同 只要一个不同&#xff0c;就是跨域。 例子 请求方响应方是否跨域原因http://www.ba…

BIO NIO AIO演变

Netty是一个提供异步事件驱动的网络应用框架&#xff0c;用以快速开发高性能、高可靠的网络服务器和客户端程序。Netty简化了网络程序的开发&#xff0c;是很多框架和公司都在使用的技术。 Netty并非横空出世&#xff0c;它是在BIO&#xff0c;NIO&#xff0c;AIO演变中的产物…

R语言分析糖尿病数据:多元线性模型、MANOVA、决策树、典型判别分析、HE图、Box's M检验可视化...

全文链接&#xff1a;https://tecdat.cn/?p33609 Reaven和Miller&#xff08;1979&#xff09;研究了145名非肥胖成年人的葡萄糖耐量和胰岛素血液化学指标之间的关系。他们使用斯坦福线性加速器中心的PRIM9系统将数据可视化为3D&#xff0c;并发现了一个奇特的图案&#xff0c…

Golang教程与Gin教程合集,入门到实战

GolangGin框架GormRbac微服务仿小米商城项目实战视频教程Docker Swarm K8s云原生分布式部署 介绍&#xff1a; Go即Golang&#xff0c;是Google公司2009年11月正式对外公开的一门编程语言&#xff0c;它不仅拥有静态编译语言的安全和高性能&#xff0c;而 且又达到了动态语言开…

将linux上的文件/文件夹下载到本地

要进行此操作 你的电脑需要有 ssh 如果没有安装 可以参考我的文章 windows系统安装SSH 其实非常简单 但您需要知道自己的文件在哪个路径下 如果不知道 例如 我知道我想下的文件叫 dist 可我不知道他在那个目录 我们可以在服务器中输入 find / -name "dist"这样 所有…

treeview形式的checkbox(wpf、c#)

如何实现treeview形式的checkbox&#xff0c;并且父节点和子节点的选中状态可相互影响。示例图&#xff1a; 代码如下&#xff1a; wpf代码&#xff1a;treeview绑定的数据是PermissionDataCollection。 <TreeView ItemsSource"{Binding PermissionDataCollection}…

只需3步,用华为云CodeArts快速搭建一个网上商城

华为云软件开发生产线CodeArts是面向开发者提供的一站式云端DevSecOps平台&#xff0c;其提供的10多个子服务覆盖了需求下发、代码提交、代码检查、代码编译、验证、部署、发布等软件交付全生命周期环节&#xff0c;提供软件研发流程的端到端支持。 华为端到端&#xff08;HE2…

ANIMALS FULL PACK (总共三十个动物)

资源包的动物包含&#xff1a;熊、野猪、鸡、牛、乌鸦、鸭子、大象、狐狸、金鹰、大雕鸮、山羊、猪、鸽子、兔子、海鸥、绵羊、麻雀、雄鹿、母鹿、狼、大象、犀牛、斑马、雄狮和母狮。此外还有一些水里的动物鲸、海豚、鲨鱼、海龟 资源链接在底部 Unity 资源商店链接 资源下载…

LLM - 批量加载 dataset 并合并

目录 一.引言 二.Dataset 生成 1.数据样式 2.批量加载 ◆ 主函数调用 ◆ 基础变量定义 ◆ 多数据集加载 3.数据集合并 ◆ Concat ◆ interleave ◆ stopping_strategy ◆ interleave_probs 三.总结 一.引言 LLM 模型基于 transformer 进行训练&#xff0c;需要先…

双token实现无感刷新

accessToken:用户获取数据权限refreshToken:用来获取新的accessToken 双 token 验证机制&#xff0c;其中 accessToken 过期时间较短&#xff0c;refreshToken 过期时间较长。当 accessToken 过期后&#xff0c;使用 refreshToken 去请求新的 token。 引入依赖 <!-- …

多版本CUDA安装切换

系统中默认的安装CUDA为12.0&#xff0c;现在需要在个人用户下安装CUDA11.7。 CUDA 下载 CUDA官网下载 安装 Log file not open.Segmentation fault (core dumped)错误 将/tmp/cuda-installer.log删除即可。重新安装&#xff0c;去掉驱动的安装&#xff0c;设置Toolkit的安装…

ST-LINK 下载器的使用

这两天我也是被这个ST-LINK搞的非常头疼&#xff0c;第一个是固件不兼容&#xff08;也就是keil5的魔法棒中显示ST-LINK connection error&#xff09;&#xff0c;第二个就是STM32 ST-LINK Utility的使用显示dll文件损坏 ST-LINK connection error 先来解决这个问题&#xff…

【附安装包】2023最新版Python安装详细教程!一键安装,永久使用

一、python官网 Python官网主要有python的About (简介)、Downloads (下载)、Documentation(文档)、Community (团体)、Success Stories (成功案例)、News (新闻)、Events (事件动态)等栏目。 Python官网地址&#xff1a;https://www.python.org/ 【领取方式见文末】 二、在…

如何选择感测型离子风机

离子风机在生产车间使用越来越广&#xff0c;对产品的要求也越来越高&#xff0c;而感测型离子风机正好满足。 感测型离子风机:内置感测和反馈功能&#xff1b;2.能快速静电中和及消除&#xff1b;高要求控制离子平衡&#xff1b;3.集感测&#xff0c;联网&#xff0c;通讯数据…

2023年数维杯数学建模C题宫内节育器的生产求解全过程文档及程序

2023年数维杯数学建模 C题 宫内节育器的生产 原题再现&#xff1a; 宫内节育器&#xff08;IUD&#xff09;是一种相对安全、有效、经济、可逆、简便&#xff0c;广大妇女易接受的节育器具&#xff0c;目前已成为我国育龄妇女的主要避孕措施。据悉&#xff0c;我国约70%妇女选…

设定excel导出时单元格的格式

一、需求 要求excel导出时&#xff0c;对应列里面的内容格式为日期&#xff0c;数值格式并有精度要求 &#xff0c;如下图&#xff1a; 使用alibaba&#xff0c;easyexcel&#xff0c;默认的导出数据格式为文本&#xff0c;excel显示为常规&#xff0c;使用数据规范注解Number…

玩转 gpgpu sim 01记 —— try it

1. 短介绍 gpgpu-sim 是一个gpu模拟器&#xff0c;可以让cuda/openCL程序运行在一个软件模拟器上&#xff0c;而不需要硬件GPU&#xff1b; 2. 目标 用最简单省事的方式跑通一个gpgpu-sim的仿真 3. gpgpu-sim 一点项目特性 开发比较早&#xff0c;没有持续的维护&#xff0…

vscode搭建Django自带后台管理系统

文章目录 一、django自带的后台管理系统1. 建表2. 后台管理系统2.1 创建账号2.2 运行后台2.3 登录 二、模版渲染1. 直接将数据渲染到页面2. 数据传递给js 三、数据库1. 查看当前数据库2. 创建UserInfo数据表3. Django rest framework配置 四、vue前端搭建1. 在Django项目的根目…

vue 使用canvas 详细教程

Vue.js 中使用 Canvas Vue.js 是一个流行的 JavaScript 框架&#xff0c;用于构建用户界面。它提供了一种简洁的方式来管理和渲染数据&#xff0c;同时也支持与其他库和工具的集成。要在 Vue.js 中使用 Canvas&#xff0c;您可以按照以下步骤进行操作&#xff1a; 在 Vue.js …