vue3+vite+uniapp 封装一个省市区组件

一、预览图

请添加图片描述

二、使用前的一些注意事项

  1. 只支持在 uniapp vue3 项目中使用
  2. 支持微信小程序和h5 (app端没有测试过)
  3. ui库用的 uview-plus
  4. 省市区数据用的是 vant-ui 提供的一个赖库 @vant/area-data

三、组件代码

<template><u-popup :show="show" type="bottom" @close="handlePopupClose" round="44rpx"><view class="area-picker"><view class="title">请选择收货地址<view class="close-icon" @click="handlePopupClose"><u-icon name="close" size="44rpx" color="#666666"></u-icon></view></view><view class="header"><view @click="doChange('province')":class="['header-item', activeType === 'province' ? 'header-item--active' : '']"v-if="activeType === 'province' || activeType === 'city' || activeType === 'district' || innerProvince">{{ innerProvince ? innerProvince.name : '请选择省' }}</view><view @click="doChange('city')" :class="['header-item', activeType === 'city' ? 'header-item--active' : '']"v-if="activeType === 'city' || activeType === 'district' || innerProvince">{{ innerProvince && innerCity ? innerCity.name : '请选择市' }}</view><view @click="doChange('district')":class="['header-item', activeType === 'district' ? 'header-item--active' : '']"v-if="activeType === 'district' || innerCity">{{ innerProvince && innerCity && innerCounty ? innerCounty.name : '请选择区' }}</view></view><scroll-view scroll-y class="main" :scroll-with-animation="true"><view :id="`tag-${item.id}`" :class="['main-item', select(item.name) ? 'main-item--active' : '']"@click="doSelect(item)" v-for="item in showList" :key="item.id"><u-icon v-if="select(item.name)" name="checkbox-mark" size="44rpx" color="#3c9cff"></u-icon>{{ item.name }}</view></scroll-view></view></u-popup>
</template>
<script setup>
import { computed, nextTick, ref } from 'vue'
import { areaList } from "@vant/area-data";const props = defineProps({show: {type: Boolean,default: false},area: {type: Array,default: () => []},id: {type: String,default: ''},
})const emits = defineEmits(['close', 'confirm']) // 事件const areaData = ref(areaList)let innerProvince = ref(null) // 选择的省
let innerCity = ref(null) // 选择的市
let innerCounty = ref(null) // 选择的区
let activeType = ref('province') // 当前所选的area类型
const viewId = ref(null) //  应当展示在视图中的节点id// 是否被选中
const select = computed(() => {return (item) => {switch (activeType.value) {case 'province':return innerProvince.value ? item === innerProvince.value.name : falsecase 'city':return innerCity.value ? item === innerCity.value.name : falsecase 'district':return innerCounty.value ? item === innerCounty.value.name : falsedefault:return innerProvince.value ? item === innerProvince.value.name : false}}
})// 展示的列表
const showList = computed(() => {switch (activeType.value) {case 'province':return provinceList.valuecase 'city':return cityList.valuecase 'district':return countyList.valuedefault:return provinceList.value}
})// 省列表
const provinceList = computed(() => {const provinceList = []if (areaData.value && areaData.value.province_list) {for (const key in areaData.value.province_list) {if (areaData.value.province_list[key]) {provinceList.push({id: key,name: areaData.value.province_list[key]})}}}return provinceList
})// 市列表
const cityList = computed(() => {const cityList = []if (areaData.value && areaData.value.city_list) {for (const key in areaData.value.city_list) {if (areaData.value.city_list[key] && innerProvince.value && innerProvince.value.id.slice(0, 2) === key.slice(0, 2)) {cityList.push({id: key,name: areaData.value.city_list[key]})}}}return cityList
})// 区列表
const countyList = computed(() => {const countyList = []if (areaData.value && areaData.value.county_list) {for (const key in areaData.value.county_list) {if (areaData.value.county_list[key] && (!innerProvince.value || (innerCity.value && innerCity.value.id.slice(0, 4) === key.slice(0, 4)))) {countyList.push({id: key,name: areaData.value.county_list[key]})}}}return countyList
})
// 关闭 popup 
function handlePopupClose() {emits('close')
}
// 地址选择完成
function doConfirm() {const list = [innerProvince.value, innerCity.value, innerCounty.value]const obj = {}list.forEach((v, i) => {i === 0 ? obj.province = v.name : ''i === 1 ? obj.city = v.name : ''i === 2 ? obj.county = v.name : ''});emits('confirm', obj, [innerProvince.value, innerCity.value, innerCounty.value])
}// 切换当前选择的省市区类型
function doChange(type) {activeType.value = type
}// 选中省市区项
function doSelect(item) {switch (activeType.value) {case 'province':if (innerProvince.value && innerProvince.value.id === item.id) {innerProvince.value = null} else {innerProvince.value = itemactiveType.value = 'city'}innerCity.value = nullinnerCounty.value = nullbreakcase 'city':if (innerCity.value && innerCity.value.id === item.id) {innerCity.value = null} else {innerCity.value = itemactiveType.value = 'district'}innerCounty.value = nullbreakcase 'district':if (innerCounty.value && innerCounty.value.id === item.id) {innerCounty.value = null} else {innerCounty.value = itemdoConfirm()}breakdefault:if (innerProvince.value && innerProvince.value.id === item.id) {innerProvince.value = null} else {innerProvince.value = itemactiveType.value = 'city'}innerCity.value = nullinnerCounty.value = nullbreak}
}
</script><style lang="scss" scoped>
$color-text-secondary: #101010;.area-picker {position: relative;height: 846rpx;height: calc(846rpx + constant(safe-area-inset-bottom));height: calc(846rpx + env(safe-area-inset-bottom));width: calc(100vw - 80rpx);background: #ffffff;padding: 0 40rpx;border-radius: 20rpx 20rpx 0px 0px;padding-bottom: 0;padding-bottom: constant(safe-area-inset-bottom);padding-bottom: env(safe-area-inset-bottom);.title {height: 114rpx;width: 100%;display: flex;align-items: center;justify-content: center;font-size: 36rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #202124;.close-icon {position: absolute;top: 57rpx;right: 0;padding: 19rpx;transform: translateY(-50%);}}.header {display: flex;margin-bottom: 24rpx;&-item {height: 44rpx;font-size: 32rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: $color-text-secondary;max-width: 186rpx;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;&:not(:last-child) {margin-right: 56rpx;}&--active {color: $u-primary;}}}.main {height: calc(100% - 182rpx);overflow: auto;::-webkit-scrollbar {width: 0;height: 0;color: transparent;}&-item {display: flex;align-items: center;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;width: 100%;height: 84rpx;background: #ffffff;font-size: 28rpx;color: $color-text-secondary;image {width: 44rpx;height: 44rpx;}&--active {font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: $color-text-secondary;}}}
}
</style>

四、组件使用

<template><view class="container"><u-button @click="show = true" type="primary" customStyle="width: 90%;margin-top: 60rpx;">选择区域</u-button><view style="text-align: center; margin-top: 60rpx;">所选区域:{{ areaText }}</view><AreaPicker :show="show" @confirm="handleConfirmArea" @close="show = false"></AreaPicker></view>
</template><script setup>
import { ref } from "vue";const show = ref(false);
const areaText = ref("");function handleConfirmArea(item) {console.log("当前选中区域:", item);const { province, city, county } = item;areaText.value = province + " " + city + " " + county;show.value = false;
}
</script><style lang="scss" scoped></style>

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

旅游网站HTML

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>旅游网</title> </head> <body><!--采用table编辑--> <!--最晚曾table,用于整个页面那布局--><table width&q…

【FPGA零基础学习之旅#14】串口发送字符串

&#x1f389;欢迎来到FPGA专栏~串口发送字符串 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家能指正…

asp.net闲置物品购物网系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net闲置物品购物网系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 asp.net 闲置物品购物网 二、功…

Euclid空间or欧式空间(定义、正交性、正交变换、对称变换)酉空间(定义、酉变换、Hermite变换、正规矩阵)

欧式空间的定义 ​​​​​例如&#xff1a; 再例如&#xff1a; 正交性 正交基与标准正交基 施密特正交化例题 正交变换与正交矩阵 ​​​​​​​对称变换与对称矩阵 正交变换与对称变换例题 酉空间介绍 ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​…

游戏软件开发与应用软件开发有什么不同呢?

游戏软件开发和应用软件开发是两种不同类型的软件开发&#xff0c;它们在许多方面都有不同之处。以下是它们之间的一些主要区别&#xff1a; 目标用户群体&#xff1a; 游戏软件开发的主要目标是提供娱乐和休闲体验&#xff0c;通常面向广大的游戏玩家群体。游戏软件的设计和开…

lua 中文字符的判断简介

一般在工作中会遇到中文字符的判断、截断、打码等需求&#xff0c;之前一直没有总结&#xff0c;虽然网上资料也多&#xff0c;今天在这里简单的总结一下。 1 .UTF-8简单描述 UTF-8 是 Unicode 的实现方式之一&#xff0c;其对应关系&#xff08;编码规则&#xff09;如下表所…

提高网站性能的10种方法:加速用户体验和降低服务器负担

在今天的数字时代&#xff0c;网站性能对于吸引和保留用户至关重要。一个快速加载的网站不仅提供更好的用户体验&#xff0c;还有助于降低服务器负担。以下是10种提高网站性能的方法&#xff0c;旨在加速页面加载速度和减少服务器的工作负荷。 压缩网页资源 利用压缩算法如gzi…

位移贴图和法线贴图的区别

位移贴图和法线贴图都是用于增强模型表面细节和真实感的纹理贴图技术&#xff0c;但是它们之间也存在着差异。 1、什么是位移贴图 位移贴图&#xff1a;位移贴图通过在模型顶点上定义位移值来改变模型表面的形状。该贴图包含了每个像素的高度值信息&#xff0c;使得模型的细节…

electron之进程间通信

Electron进程间通信 使用electron编写程序时经常遇到下面这种场景&#xff1a; 当用户点击一个按钮时&#xff0c;需要将页面输入的信息保存到本地电脑上&#xff1b; 或者是点击菜单时&#xff0c;需要页面窗口做出响应。 用户点击的按钮和窗口展示的内容是运行在渲染进程中&…

【JavaEE初阶】 线程的状态和转移

文章目录 &#x1f332;线程的状态&#x1f340;观察线程的所有状态&#x1f38d;线程状态和状态转移的意义&#x1f38b;观察线程的状态和转移&#x1f4cc;观察 1:&#x1f4cc;观察 2:&#x1f4cc;观察-3: ⭕总结 &#x1f332;线程的状态 &#x1f340;观察线程的所有状态…

怎样开始用selenium进行自动化测试?

如果您刚开始使用 Selenium 进行自动化测试&#xff0c;以下是建议的步骤。 1、安装 Selenium 首先&#xff0c;您需要安装 Selenium。Selenium 支持多种编程语言&#xff0c;如 Python、Java、C# 等。可以通过 pip 命令在 Python 中安装 Selenium&#xff1a; pip install …

化妆品用乙基己基甘油全球市场总体规模2023-2029

乙基己基甘油又名辛氧基甘油&#xff0c;分子式 C11H24O3&#xff0c;分子量 204.306&#xff0c;沸点 325℃&#xff0c;密度 0.962&#xff0c;无色液体&#xff0c;涂抹性能适中的润肤剂、保湿剂及润湿剂。它能够在提高配方滋润效果的同时又具有柔滑的肤感。加入在某些膏霜体…