uni-popup封装省市区级联选择器组件

<template>
    
        <view>
            <uni-popup ref="popup" type="bottom" :is-mask-click="false" :mask-click="false" border-radius="10px 10px 0 0" mask-background-color="rgba(0,0,0,0.1)">
                <view class="customer-type-selection-main-style">
                    <view style="flex: 1;"></view>
                    <view class="customer-type-selection-style content">
                        <view class="customer-type-selection-title-style">请选择</view>
                        <view class="content_box">
							<!-- 省 -->
							<view class="item_box">
								<view v-for="(item, index) in prevince" :key="index" v-if="prevince.length > 0">
                                 	<view :class="{activeStyle: previnceActive === index }" class="customer-type-selection-content-style" @click="checkItem1(item, index)">{{item}}</view>
                           		</view>
							</view>
							<!-- 市 -->
							<view class="item_box">
								<view v-for="(item, index) in city" :key="index" v-if="city.length > 0">
									<view :class="{activeStyle: cityActive === index }" class="customer-type-selection-content-style" @click="checkItem2(item,index)">{{item}}</view>
								</view>
							</view>
							<!-- 区 -->
							<!-- 户籍地址不展示区 -->
							<view class="item_box" v-if="keywords !== 'RegisteredProvince'">
								<view v-for="(item, index) in county" :key="index" v-if="county.length > 0">
									<view :class="{activeStyle: countyActive === index }" class="customer-type-selection-content-style" @click="checkItem3(item,index)">{{item}}</view>
								</view>
							</view>
							
							<!-- <view class="emptyMsg" v-if="mode == 1 && city.length == 0">请先选择所属省份</view> -->
							<!-- <view class="emptyMsg" v-if="mode == 2 && county.length == 0">请先选择所属省份</view> -->
                        </view>
                    </view>
                </view>
            </uni-popup>
        </view>
</template>
<script setup>
import { reactive, ref } from 'vue';
// 弹框
const popup = ref(null);
// 父组件传来的值
const props = defineProps([ 'keywords' ])
// 省
let prevince = reactive([
    '广东省', '湖南省','云南省', '江西省','山东省', '北京省','广东省', '湖南省','云南省', '江西省','山东省', '北京省','广东省', '湖南省','云南省', '江西省','山东省', '北京省'
])
// 选中下标
let previnceActive = ref(null)

// 市
let city = reactive(['h市', 'a市', 's市','h市', 'a市', 's市','h市', 'a市', 's市','h市', 'a市', 's市','h市', 'a市', 's市'])
// 选中下标
let cityActive = ref(null)

// 区
let county = reactive(['海定区', '四环区', '天海区'])
// 选中下标
let countyActive = ref(null)

// 选中数据
let addrData = {
	prevince:{
		addrName: '',
		code: ''
	},
	city:{
		addrName: '',
		code: ''
	},
	county:{
		addrName: '',
		code: ''
	}
}

const open = () => {
    popup.value.open('bottom')
}

// 父组件调用该方法进行渲染列表
const renderList = (list) => {
    console.log(list, '父组件给的列表')
}

let emits = defineEmits([`informData`])

// 点击省
const checkItem1 = (val,index) => {
    console.log(val)
	// addrData[0] = val
	addrData.prevince.addrName = val
	previnceActive.value = index
}
// 点击市
const checkItem2 = (val,index) => {
    console.log(val)
	// addrData[1] = val
	addrData.city.addrName = val
	cityActive.value = index
	console.log(props.keywords, '子组件的keywords')
	if (props.keywords === 'RegisteredProvince') {
		// 户籍地址仅需要省市内容
		emits(`informData`, addrData)
		setTimeout(() => {
		popup.value.close('bottom')
		reset()
	}, 200)
	}
    // emits(`informData`, val) // 调用父组件方法并传值 @informData="informData"
}
// 点击区
const checkItem3 = (val,index) => {
    console.log(val)
	// addrData[2] = val
	addrData.county.addrName = val
	countyActive.value = index
	console.log(addrData, '选中的省市区')
    emits(`informData`, addrData)
	setTimeout(() => {
		popup.value.close('bottom')
		reset()
	}, 200)
}

// 清空数据
const reset = () => {
	// city.length = 0
	// county.length = 0
	previnceActive.value = null
	cityActive.value = null
	countyActive.value = null
	addrData = {
		prevince:{
			addrName: '',
			code: ''
		},
		city:{
			addrName: '',
			code: ''
		},
		county:{
			addrName: '',
			code: ''
		}
	}
}

defineExpose({ renderList, open })
</script>
<style>
.content_box{
	display: flex;
	overflow: auto;
	margin-top: 12px;
}
.item_box{
	overflow: auto;
	height: 100%;
	flex:1;
	padding: 0 2px;
}

.content{
    background-color: #fff;
}
.activeStyle{
	background-color: #eee;
	
}
/* .customer-type-selection-main-style {
		left: 0;
		top: 0;
		position: absolute;
		width: 100%;
		height: 100vh;
		display: flex;
		flex-direction: column;
	} */
	
    .customer-type-selection-style {
		width: 100%;
		height: 400px;
		border-radius: 6px 6px, 0px, 0px;
		background: #fff;
		box-shadow: 0px -1px 10px rgba(0, 0, 0, 0.1);
		display: flex;
		padding-bottom: 10px;
		flex-direction: column;
	}
    .customer-type-selection-title-style {
		height: 23px;
		margin-top: 10px;
		font-size: 16px;
		font-weight: 700;
		letter-spacing: 0px;
		/* line-height: 22.4px; */
		color: rgba(51, 51, 51, 1);
		text-align: center;
		vertical-align: top;
		
	}
    .customer-type-selection-content-style {
		margin-top: 10px;
		font-size: 16px;
		font-weight: 500;
		letter-spacing: 0px;
		line-height: 22.4px;
		color: rgba(51, 51, 51, 1);
		text-align: center;
		vertical-align: top;
		padding:6px 0;
	} 
	.emptyMsg{
		padding:12px;
		text-align: center;
		color: gray;
	}
</style>

效果图

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值