移动端城市筛选组件---锚点滚动

1.组件代码

<template>
	<!-- 地址筛选 -->
	<u-popup :show="visible" @close="closeVisible" @open="openVisible" round="10" closeable bgColor="#F8F8F8">
		<view class="city-popup">
			<view class="title">
				推荐地址
			</view>
			<view class="recommen-city">
				<span v-for="(item,index) in recommen" :key="index"
					:class="{'active-city':city.includes(item)}" @click="handleCity(item)">{{item}}</span>
			</view>
			<view class="letter-city">
				<view class="left-letter">
					<a v-for="(item,index) in letterList" :key="index"
						:class="currentViewId==`section-${item}`?'letter-item active-letter':'letter-item'"
						@click="scrollToSection(item)">{{item}}</a>
				</view>
				<scroll-view class="right-city" scroll-y :scroll-into-view="currentViewId" scroll-with-animation
					:scroll-top="scrollTop">
					<view v-for="(e, index) in cityList" :key="index" :id="'section-'+e.letter">
						<view class="province-group">
							<view class="group-title">{{ e.province }}:</view>
							<view class="city-list">
								<view v-for="(i, k) in e.children" :key="k" :class="city.includes(i.name)?'city-item active-item':'city-item'"
									@click="selectProvince(i)">
									{{ i.name }}
								</view>
							</view>
						</view>
					</view>
				</scroll-view>
			</view>
		</view>
	</u-popup>
</template>

<script>
	export default {
		name: "city-select",
		props: {
			visible: {
				type: Boolean,
				default: true
			},
			city: {
				type: String,
				default: ''
			},
			cityList: {
				type: Array,
				default: () => []
			},
			letterList: {
				type: Array,
				default: () => []
			},
		},
		data() {
			return {
				currentViewId: '',
				recommen: ['西安', '北京', '重庆', '洛阳', '大理', '汉中', '榆林', '洛阳', '大理', '汉中', '榆林'],
			};
		},
		onShow() {

		},
		watch: {

		},
		methods: {
			openVisible() {
				this.$emit('openCity', true)
			},
			closeVisible() {
				this.$emit('closeCity', false)
			},
			scrollToSection(letter) {
				this.currentViewId = 'section-' + letter;
			},
			selectProvince(city) {
				this.$emit('changeCity', city.name)
				this.closeVisible()
			},
			handleCity(city) {
				let str = ''
				if(!city.includes('市')){
					str = city + '市'
				}else{
					str =  city
				}
				this.$emit('changeCity', str)
				this.closeVisible()
			}
		}
	}
</script>

<style lang="scss">
	.city-popup {
		.title {
			height: 7vh;
			line-height: 7vh;
			font-weight: bold;
			font-size: 31rpx;
			color: #000000;
			border-bottom: 2rpx solid #E4E4E4;
			background-color: #fff;
			padding: 0 26rpx;
			box-sizing: border-box;
		}

		.recommen-city {
			background-color: #fff;
			padding: 26rpx;
			box-sizing: border-box;
			display: grid;
			grid-template-columns: repeat(4, 1fr);
			gap: 20rpx;
			margin-bottom: 10rpx;

			span {
				line-height: 50rpx;
				font-weight: 500;
				font-size: 25rpx;
				color: #999999;
				text-align: center;
				background: #F3F5F9;
				border-radius: 9rpx;
			}

			.active-city {
				background: #D7FAF6 !important;
				color: #009F9A !important;
			}
		}

		.letter-city {
			height: 60vh;
			display: flex;

			.left-letter {
				width: 130rpx;
				height: 100%;
				overflow: auto;
				padding: 26rpx 0;
				box-sizing: border-box;
				background-color: #fff;
				margin-right: 10rpx;
				.letter-item{
					font-weight: 500;
					font-size: 31rpx;
					color: #666666;
					line-height: 56rpx;
					border-radius: 9rpx;
					margin-bottom: 40rpx;
					text-align: center;
				}
				.active-letter{
					background: linear-gradient( 90deg, #4BFFAB 0%, #00A37C 100%) !important;
					color: #fff !important;
				}
			}

			.right-city {
				flex: 1;
				overflow: auto;
				padding: 26rpx;
				box-sizing: border-box;
				background-color: #fff;

				.province-group {
					margin-bottom: 30rpx;

					.group-title {
						font-weight: 500;
						font-size: 29rpx;
						color: #333333;
						margin-bottom: 20rpx;
					}

					.city-list {
						display: grid;
						grid-template-columns: repeat(3, 1fr);
						gap: 20rpx;

						.city-item {
							line-height: 50rpx;
							font-weight: 500;
							font-size: 24rpx;
							color: #999999;
							text-align: center;
							background: #F3F5F9;
							border-radius: 9rpx;
						}

						.active-item {
							background: #D7FAF6 !important;
							color: #009F9A !important;
						}
					}
				}
			}
		}
	}
</style>

2.父组件引用

import citySelect from '@/components/city-select/city-select.vue';

//组件注册

components: {
			citySelect
		},

3.父组件所需data

city: uni.getStorageSync('userCity')?uni.getStorageSync('userCity'):'北京',
				isAddressShow: false,
				cityList: [],
				letterList:[],


//上面数组内容模拟数据如下   具体可根据个人接口重新整理

cityList:[

   {
      children: [,…]
0: {id: 340800, parent_id: 340000, name: "安庆市", province: "安徽省", city: "安庆市", letter: "A", children: []}
1: {id: 340300, parent_id: 340000, name: "蚌埠市", province: "安徽省", city: "蚌埠市", letter: "B", children: []}
2: {id: 341600, parent_id: 340000, name: "亳州市", province: "安徽省", city: "亳州市", letter: "B", children: []}
3: {id: 341100, parent_id: 340000, name: "滁州市", province: "安徽省", city: "滁州市", letter: "C", children: []}
4: {id: 341700, parent_id: 340000, name: "池州市", province: "安徽省", city: "池州市", letter: "C", children: []}
5: {id: 341200, parent_id: 340000, name: "阜阳市", province: "安徽省", city: "阜阳市", letter: "F", children: []}
6: {id: 340100, parent_id: 340000, name: "合肥市", province: "安徽省", city: "合肥市", letter: "H", children: []}
7: {id: 340400, parent_id: 340000, name: "淮南市", province: "安徽省", city: "淮南市", letter: "H", children: []}
8: {id: 340600, parent_id: 340000, name: "淮北市", province: "安徽省", city: "淮北市", letter: "H", children: []}
9: {id: 341000, parent_id: 340000, name: "黄山市", province: "安徽省", city: "黄山市", letter: "H", children: []}
10: {id: 341500, parent_id: 340000, name: "六安市", province: "安徽省", city: "六安市", letter: "L", children: []}
11: {id: 340500, parent_id: 340000, name: "马鞍山市", province: "安徽省", city: "马鞍山市", letter: "M", children: []}
12: {id: 341300, parent_id: 340000, name: "宿州市", province: "安徽省", city: "宿州市", letter: "S", children: []}
13: {id: 340700, parent_id: 340000, name: "铜陵市", province: "安徽省", city: "铜陵市", letter: "T", children: []}
14: {id: 340200, parent_id: 340000, name: "芜湖市", province: "安徽省", city: "芜湖市", letter: "W", children: []}
15: {id: 341800, parent_id: 340000, name: "宣城市", province: "安徽省", city: "宣城市", letter: "X", children: []}
city: ""
id: 340000
letter: "A"
name: "安徽省"
parent_id: 100000
province: "安徽省"

   }
]

4.父组件定义函数传递子组件

//接口获取省市数据
getCity() {
				this.$http.get('你自己的接口url', {}, {
					custom: {
						loading: false,
						auth: false
					}
				}).then(res => {
					console.log('城市信息', res);
					if (res.code == 0) {
						let arr = res.data.map(e=>{
							return e.letter
						})
						this.letterList = [...new Set(arr)]
						this.cityList = res.data
						
					}
				})
			},


openCity(val) {
				this.isAddressShow = val
			},
			closeCity(val) {
				this.isAddressShow = val
			},
			changeCity(val){
				uni.setStorageSync('userCity',val)
				this.city = val
			},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值