Bootstrap

uniapp省市区懒加载封装

一、z-region.vue  直接复制就可用,需要修改请求接口  getAddressList

vue2和vue3皆可使用(微信小程序,H5支持)

<template>
	<view>
		<view class="list">
			<picker class="picker" mode="multiSelector" :range="region" range-key="name" :value="regionIndex"
				@change="pickerChange" @columnchange="pickerColumnchange">
				<view class="pbox" :class="{'pbox_hover':regionStr != '请选择'}">
					<view class="region-str" :style="{textAlign: inputAlign}">{{regionStr}}</view>
					<text class="iconfont icon-you"></text>
				</view>
			</picker>
		</view>
	</view>
</template>

<script>
	import {
		getAddressList,
	} from '@/api/address/index.js'
	export default {
		data() {
			return {
				// 原数组
				oldRegion: [],
				// 处理后的数组
				region: [
					[],
					[],
					[]
				],
				// 选择省市区的下标Index
				regionIndex: [0, 0, 0],
				// 省市区字符串
				regionStr: '请选择'
			};
		},
		props: {
			height: {
				type: [Number],
				default: 92
			},
			width: {
				type: [Number],
				default: 710
			},
			previnceId: {
				type: [Number],
				default: 11
			},
			cityId: {
				type: [Number],
				default: 1101
			},
			countyId: {
				type: [Number],
				default: 110101
			},
			isRevise: {
				type: [Boolean],
				default: false
			},
			inputAlign: {
				type: [String],
				default: 'right'
			},
			country: {
				type: [String],
				default: 'domestic'
			}
		},
		methods: {
			pickerChange(e) {
				this.regionIndex = e.detail.value;
				if (this.region[2].length > 0) {
					this.regionStr = this.region[2][this.regionIndex[2]].name;

					// 组件传值,返回所需格式
					this.$emit('region', {
						name: this.region[2][this.regionIndex[2]].name,
						code: this.region[2][this.regionIndex[2]].code
					});
				}
			},
			pickerColumnchange(e) {
				if (e.detail.column === 0) {
					// 选择了省,发起请求获取城市
					this.regionIndex = [e.detail.value, 0, 0];
					this.loadCities(this.region[0][e.detail.value].code);
				} else if (e.detail.column === 1) {
					// 选择了城市,发起请求获取县区
					this.regionIndex[1] = e.detail.value;
					this.regionIndex[2] = 0;
					this.loadCounties(this.region[1][e.detail.value].code);
					// this.regionIndex[1] = e.detail.value;
					// this.regionIndex[2] = 0; // 重置县区选择
				} else if (e.detail.column === 2) {
					this.regionIndex[2] = e.detail.value;
				}
			},
			loadCities(provinceCode) {
				getAddressList({
					parentCode: provinceCode
				}).then((response) => {
					const cityArr = response.data.map(item => ({
						name: item.name,
						code: item.code
					}));
					this.$set(this.region, 1, cityArr);
					if (cityArr.length > 0) {
						this.loadCounties(cityArr[0].code); // 默认加载第一个城市的县区
					}
				})
			},
			loadCounties(cityCode) {

				getAddressList({
					parentCode: cityCode
				}).then((response) => {
					const countyArr = response.data.map(item => ({
						name: item.name,
						code: item.code
					}));
					this.$set(this.region, 2, countyArr);
				})
			},

			getAddress() {
					getAddressList({
						parentCode: 0
					}).then((response) => {
						this.oldRegion = response.data;

						// 在 region[0] 数组的开头添加“请选择”选项
						this.region[0].push({
							name: '请选择',
							code: null // 或者使用一个特定的值,表示未选择
						});

						this.oldRegion.map((item, index) => {
							this.region[0].push({
								name: item.name,
								code: item.code
							});
							if (this.previnceId == item.code) {
								this.regionIndex[0] = index;
								if (item.code !== null) {
									this.loadCities(item.code); // 加载选中省的城市
								}
							}
						});
					})
			}
		},

		created() {
			// 初始加载省份
			this.getAddress();
		}
	}
</script>

<style lang="scss" scoped>
	.list {
		padding: 0 8rpx;
		box-sizing: border-box;
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		position: relative;

		.picker {
			flex: 1;
			height: 92rpx;

			.pbox {
				width: 100%;
				height: 92rpx;
				display: flex;
				flex-direction: row;
				align-items: center;
				justify-content: space-between;
				color: #808080;

				.region-str {
					width: 100%;
				}

				.icon-you {
					font-size: 28rpx;
				}
			}

			.pbox_hover {
				color: #383838;
			}
		}

		.name {
			width: 168rpx;
			font-size: 32rpx;
			color: #383838;
		}

		.icon-you {
			font-size: 28rpx;
			color: #999999;
		}

		.input {
			flex: 1;
			height: 100%;
			line-height: 92rpx;
			color: #9080A1;
		}

		.textarea {
			flex: 1;
			height: 100%;
			color: #A9A9A9;
		}
	}
</style>

二、页面中使用

<template>
    <view>
		<Region @region="resgclick">
	</view>
</template>


<script setup>
    /** 引入 */
	import Region from '@/components/w-region.vue';

    // 起始地行政区划
	function resgclick(e) {

        /** 本人是需要区的名称和code,所以只返回了区的,若想全部返回请看(三) */
		form.value.qsd = e.name;
		form.value.qsdCode = e.code;
	}

</script>

三、返回全部(省市区)名称和code

/** 修改w-region中的代码 */

pickerChange(e) {
				this.regionIndex = e.detail.value;
				if (this.region[2].length > 0) {
					this.regionStr = this.region[2][this.regionIndex[2]].name;

					// 组件传值,返回所需格式
					this.$emit('region', {
						name: [
                            this.region[0][this.regionIndex[0]].name
                            this.region[1][this.regionIndex[1]].name
                            this.region[2][this.regionIndex[2]].name
                        ],
						code: [
                            this.region[0][this.regionIndex[0]].code
                            this.region[1][this.regionIndex[1]].code
                            this.region[2][this.regionIndex[2]].code
                        ]
					});
				}
			},

我也是拿其他 大佬 的进行修改的(只不过他的是本地数据,内容太大),所以进行了修改,若是遇到问题 欢迎讨论

;