uniapp:省市选择 自定义组件

源码

https://gitee.com/river-winter/unappCity

效果图

湾流

两个数据文件

热门城市
common/hotData.js

export default [{ name: "上海市", },{ name: "广州市", },
{ name: "北京市", },{ name: "天津市", },{ name: "重庆市", },
{ name: "深圳市", },{name: "佛山市", },{ name: "东莞市", },
{ name: "杭州市", },{ name: "宁波市", },{ name: "南京市", },
{ name: "苏州市", },{ name: "福州市", },{name: "厦门市", },
{ name: "泉州市", },{ name: "济南市", },{ name: "青岛市", },
{ name: "武汉市", },{ name: "成都市", },{ name: "郑州市", },
{name: "长沙市", },{ name: "其他城市",},
]

省市数据
common/cityData.js

export default {
	"a": ["北京市", "天津市", "河北省", "山西省", "内蒙古自治区", "辽宁省", "吉林省", "黑龙江省", "上海市", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省",
		"河南省", "湖北省", "湖南省", "广东省", "广西壮族自治区", "海南省", "重庆市", "四川省", "贵州省", "云南省", "西藏自治区", "陕西省", "甘肃省", "青海省",
		"宁夏回族自治区", "新疆维吾尔自治区", "台湾省", "香港特别行政区", "澳门特别行政区"
	],
	"o": {
		"0": ["北京市"],
		"1": ["天津市"],
		"2": ["石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市", "省直辖县级行政区划"],
		"3": ["太原市", "大同市", "阳泉市", "长治市", "晋城市", "朔州市", "晋中市", "运城市", "忻州市", "临汾市", "吕梁市"],
		"4": ["呼和浩特市", "包头市", "乌海市", "赤峰市", "通辽市", "鄂尔多斯市", "呼伦贝尔市", "巴彦淖尔市", "乌兰察布市", "兴安盟", "锡林郭勒盟", "阿拉善盟"],
		"5": ["沈阳市", "大连市", "鞍山市", "抚顺市", "本溪市", "丹东市", "锦州市", "营口市", "阜新市", "辽阳市", "盘锦市", "铁岭市", "朝阳市", "葫芦岛市"],
		"6": ["长春市", "吉林市", "四平市", "辽源市", "通化市", "白山市", "松原市", "白城市", "延边朝鲜族自治州"],
		"7": ["哈尔滨市", "齐齐哈尔市", "鸡西市", "鹤岗市", "双鸭山市", "大庆市", "伊春市", "佳木斯市", "七台河市", "牡丹江市", "黑河市", "绥化市", "大兴安岭地区"],
		"8": ["上海市"],
		"9": ["南京市", "无锡市", "徐州市", "常州市", "苏州市", "南通市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市"],
		"10": ["杭州市", "宁波市", "温州市", "嘉兴市", "湖州市", "绍兴市", "金华市", "衢州市", "舟山市", "台州市", "丽水市"],
		"11": ["合肥市", "芜湖市", "蚌埠市", "淮南市", "马鞍山市", "淮北市", "铜陵市", "安庆市", "黄山市", "滁州市", "阜阳市", "宿州市", "六安市", "亳州市", "池州市",
			"宣城市"
		],
		"12": ["福州市", "厦门市", "莆田市", "三明市", "泉州市", "漳州市", "南平市", "龙岩市", "宁德市"],
		"13": ["南昌市", "景德镇市", "萍乡市", "九江市", "新余市", "鹰潭市", "赣州市", "吉安市", "宜春市", "抚州市", "上饶市"],
		"14": ["济南市", "青岛市", "淄博市", "枣庄市", "东营市", "烟台市", "潍坊市", "济宁市", "泰安市", "威海市", "日照市", "莱芜市", "临沂市", "德州市", "聊城市",
			"滨州市", "菏泽市"
		],
		"15": ["郑州市", "开封市", "洛阳市", "平顶山市", "安阳市", "鹤壁市", "新乡市", "焦作市", "濮阳市", "许昌市", "漯河市", "三门峡市", "南阳市", "商丘市",
			"信阳市", "周口市", "驻马店市", "省直辖县级行政区划"
		],
		"16": ["武汉市", "黄石市", "十堰市", "宜昌市", "襄阳市", "鄂州市", "荆门市", "孝感市", "荆州市", "黄冈市", "咸宁市", "随州市", "恩施土家族苗族自治州",
			"省直辖县级行政区划"
		],
		"17": ["长沙市", "株洲市", "湘潭市", "衡阳市", "邵阳市", "岳阳市", "常德市", "张家界市", "益阳市", "郴州市", "永州市", "怀化市", "娄底市",
			"湘西土家族苗族自治州"],
		"18": ["广州市", "韶关市", "深圳市", "珠海市", "汕头市", "佛山市", "江门市", "湛江市", "茂名市", "肇庆市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市",
			"清远市", "东莞市", "中山市", "潮州市", "揭阳市", "云浮市"
		],
		"19": ["南宁市", "柳州市", "桂林市", "梧州市", "北海市", "防城港市", "钦州市", "贵港市", "玉林市", "百色市", "贺州市", "河池市", "来宾市", "崇左市"],
		"20": ["海口市", "三亚市", "三沙市", "儋州市", "省直辖县级行政区划"],
		"21": ["重庆市"],
		"22": ["成都市", "自贡市", "攀枝花市", "泸州市", "德阳市", "绵阳市", "广元市", "遂宁市", "内江市", "乐山市", "南充市", "眉山市", "宜宾市", "广安市", "达州市",
			"雅安市", "巴中市", "资阳市", "阿坝藏族羌族自治州", "甘孜藏族自治州", "凉山彝族自治州"
		],
		"23": ["贵阳市", "六盘水市", "遵义市", "安顺市", "毕节市", "铜仁市", "黔西南布依族苗族自治州", "黔东南苗族侗族自治州", "黔南布依族苗族自治州"],
		"24": ["昆明市", "曲靖市", "玉溪市", "保山市", "昭通市", "丽江市", "普洱市", "临沧市", "楚雄彝族自治州", "红河哈尼族彝族自治州", "文山壮族苗族自治州",
			"西双版纳傣族自治州", "大理白族自治州", "德宏傣族景颇族自治州", "怒江傈僳族自治州", "迪庆藏族自治州"
		],
		"25": ["拉萨市", "日喀则市", "昌都市", "林芝市", "山南市", "那曲地区", "阿里地区"],
		"26": ["西安市", "铜川市", "宝鸡市", "咸阳市", "渭南市", "延安市", "汉中市", "榆林市", "安康市", "商洛市"],
		"27": ["兰州市", "嘉峪关市", "金昌市", "白银市", "天水市", "武威市", "张掖市", "平凉市", "酒泉市", "庆阳市", "定西市", "陇南市", "临夏回族自治州",
			"甘南藏族自治州"],
		"28": ["西宁市", "海东市", "海北藏族自治州", "黄南藏族自治州", "海南藏族自治州", "果洛藏族自治州", "玉树藏族自治州", "海西蒙古族藏族自治州"],
		"29": ["银川市", "石嘴山市", "吴忠市", "固原市", "中卫市"],
		"30": ["乌鲁木齐市", "克拉玛依市", "吐鲁番市", "哈密市", "昌吉回族自治州", "博尔塔拉蒙古自治州", "巴音郭楞蒙古自治州", "阿克苏地区", "克孜勒苏柯尔克孜自治州", "喀什地区",
			"和田地区", "伊犁哈萨克自治州", "塔城地区", "阿勒泰地区", "自治区直辖县级行政区划"
		],
		"31": ["台北市", "高雄市", "台南市", "台中市", "金门县", "南投县", "基隆市", "新竹市", "嘉义市", "新北市", "宜兰县", "新竹县", "桃园县", "苗栗县", "彰化县",
			"嘉义县", "云林县", "屏东县", "台东县", "花莲县", "澎湖县"
		],
		"32": ["香港岛", "九龙", "新界"],
		"33": ["澳门半岛", "氹仔岛", "路环岛"]
	}
}

组件页

pages/index/city.vue

<template>
	<view class="city">
		<view class="city_item flex1">
			<!-- 左侧滑动导航栏 -->
			<view class="city_item_left color81">
				<scroll-view :scroll-y="true" style="height:calc(100vh - 88rpx);">
					<view :class="indexsp == 'hot' ? 'active' : ''" @tap="setProvince" data-index="hot">
						常见&热门
					</view>
					<view :class="indexsp == index ? 'active' : ''" v-for="(item,index) in province.a"
						@tap="setProvince" :data-index="index">{{item}}</view>
				</scroll-view>
			</view>
			<!-- 右侧选择导航栏 -->
			<view class="city_item_right">
				<!-- 选中城市展示 -->
				<view class="current">
					<text class="hot_title">当前选择城市:</text>
					<view class="flex1">
						<!-- <imgParts url="../../static/icon/address.png" class="icon" width="25" height="30" /> -->
						<view>
							<text v-for="(item,index) in current" @click="setCity(item)">{{item}}{{index != (current.length-1) ? '、' : ''}}</text>
						</view>
					</view>
				</view>
				<!-- 城市选项展示 -->
				<view>
					<!-- 热门城市选项 -->
					<view class="hot" v-if="indexsp == 'hot'">
						<button v-for="(item,index) in hotlist" v-if="item.name != '其他城市'"
							:class="indexOfs(current,item.name) ? 'active' : ''"
							@tap="setCity(item.name)">{{item.name}}</button>
					</view>
					<!-- 城市选项 -->
					<view class="hot" v-else>
						<!-- 根据侧边导航选项索引决定右侧渲染的城市数据 -->
						<button v-for="(item,index) in province.o[indexsp]" @tap="setCity(item)"
							:class="indexOfs(current,item) ? 'active' : ''">{{item}}</button>
					</view>
					<!-- 确认按钮 -->
					<button class="submit f08btn" @tap="back">确定</button>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	// 导入省市数据
	import cityData from '@/common/cityData.js';
	// 导入热门城市数据
	import hotData from '@/common/hotData.js'
	export default {
		data() {
			return {
				// 省市数据
				province: cityData,
				// 侧边导航选项索引
				indexsp: 'hot',
				// 选中城市数组
				current: [],
				// 热门城市数据
				hotlist: hotData
			};
		},
		onLoad(options) {
			let that = this;
			// 将页面传递过来的数据使用"|"符号分割开,存储到变量current中
			that.current = options.city ? options.city.split('|') : [];
		},
		methods: {
			indexOfs(list, name) {
				return list.indexOf(name) != -1;
			},
			setCity(city) {// city 当前点击的城市
				
				let that = this;
				// 选中的城市数组
				let current = that.current;
				// 将当前点击城市在选中城市数组中检索,将结果赋值给变量index
				let index = current.indexOf(city);
				
				if (index != -1) {//index不等于-1代表选中数组中已有当前点击城市
					//从返回的城市数组位置进行删除一个元素
					that.current.splice(index, 1)
					
				} else if (current.length < 4) {// 当选中的城市数少于4个时
					// 将当前点击城市push进选中城市数组
					that.current.push(city);
				} else {//弹窗提示,选中城市不能超过4个
					uni.showToast({
						title: '城市不能超过4个',
						icon: 'none'
					})
				}
			},
			// 确定按钮触发函数
			back() {
				// 将数据通过|符号切割开
				let city = this.current.join('|');
				// 组件传值
				uni.$emit('setCity', city);
				// 返回上一个页面
				uni.navigateBack({
					delta:1
				})
			},
			// 侧边导航点击处理函数
			setProvince(e) {
				// 将点击元素的索引赋值到变量indexsp中
				this.indexsp = e.currentTarget.dataset.index;
			}
		}
	}
</script>

<style lang="scss" scoped>
	.submit {
		position: fixed;
		bottom: 10rpx;
		width: 500rpx
	}

	.f08btn {
		background-color: #f08300 !important;
		color: #fff;
		font-size: 28rpx;
	}

	.city {
		width: 100%;

		&_title {
			margin-bottom: 60rpx;
		}

		&_item {
			padding-bottom: 20rpx;
			align-items: flex-start;

			&_left {
				width: 210rpx;
				display: inline-block;
				background: #fafafa;

				view {
					text-align: center;
					padding: 20rpx;
				}

				.active {
					color: #f08300;
					background: #fff;
				}
			}

			&_right {
				width: 500rpx;
				display: inline-block;
				padding-left: 20rpx;
				position: fixed;

				button {
					border: 1rpx solid #f6f6f6;
				}

				.current {
					padding: 20rpx 30rpx 0 0;
					// 当前城市样式
					.hot_title {
						width: 100%;
						display: inline-block;
						color: #bfbfbf;
						line-height: 1;
						vertical-align: middle;
						margin-bottom: 22rpx;
					}
					.flex1{
						color: orange;
						.data-v-57280228{
						}
						text{
							font-size: 14px;
						}
					}

					.icon {
						width: 30rpx;
						height: 35rpx;
						display: inline-block;
						vertical-align: middle;
					}

					view {
						
						justify-content: space-between;

						view {
							width: calc(100% - 40rpx);

							text {
								display: inline-block;
							}
						}
					}
				}

				.hot {
					button {
						color: #484848;
						min-width: calc(50% - 20rpx);
						height: 65rpx;
						background: #fff;
						padding: 0 12rpx;
						display: inline-block;
						font-size: 24rpx;
						margin: 18rpx 20rpx 0 0;
					}

					button:after {
						border-color: #eee;
					}

					.active {
						color: #f08300;
						border: 1rpx solid #f08300;
					}

					.active:after {
						border-color: #f08300;
					}

				}
			}
		}

	}
</style>

引入页

pages/index/index.vue

<template>
	<!-- 带着已选城市为参数跳转到城市选择页 -->
	<navigator :url="`./city?city=${form.city}`" class="nav">
		<text>{{form.city ? form.city : '未选择城市'}}</text>
	</navigator>
</template>

<script>
	export default{
		data(){
			return{
				// 选中的城市
				form:{
					city:''
				}
			}
		},
		// 从跳转页面返回时触发的周期函数
		onShow(){
			let that=this
			// 使用$on接收组件传过来的值
			uni.$on('setCity',function(name){
				// 将选择的城市数据保存到form.city中
				that.form.city=name
			})
		}
	}
</script>

<style lang="scss"  scoped>
	.nav{
		height: 60rpx;
		text{
			color: orange;
		}
	}
</style>

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
UniApp 是一个基于 Vue.js 的跨平台开发框架,可以用来开发微信小程序、H5、App等多个平台的应用。在 UniApp 中,可以通过自定义组件来实现对小程序的扩展和复用。 要创建一个自定义组件,可以按照以下步骤进行: 1. 在 UniApp 项目的 `components` 目录下创建一个新的文件夹,用于存放自定义组件的相关文件。 2. 在该文件夹下创建一个 `.vue` 文件,作为自定义组件的入口文件。 3. 在入口文件中定义组件的模板、样式和逻辑代码。 4. 在需要使用自定义组件的页面或组件中,引入并使用该自定义组件。 下面是一个简单的示例,演示如何创建一个自定义组件: 1. 在 `components` 目录下创建一个名为 `my-component` 的文件夹。 2. 在 `my-component` 文件夹下创建一个名为 `my-component.vue` 的文件,作为自定义组件的入口文件。 3. 在 `my-component.vue` 文件中编写如下代码: ```html <template> <view class="my-component"> <text>{{ message }}</text> </view> </template> <script> export default { name: 'MyComponent', props: { message: { type: String, default: '' } } } </script> <style scoped> .my-component { color: red; } </style> ``` 4. 在需要使用自定义组件的页面或组件中,引入并使用该自定义组件。例如,在某个页面的 `.vue` 文件中: ```html <template> <view> <my-component message="Hello World"></my-component> </view> </template> <script> import MyComponent from '@/components/my-component/my-component.vue' export default { components: { MyComponent } } </script> ``` 这样,就可以在页面中使用名为 `my-component` 的自定义组件了。 需要注意的是,自定义组件的文件夹和文件名可以根据实际情况进行命名,但要保持一致性。另外,自定义组件中的样式可以使用 `scoped` 关键字来实现样式的隔离,避免与其他组件的样式冲突。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

湾流~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值