当前位置: 首页 > news >正文

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>

相关文章:

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

一、预览图 二、使用前的一些注意事项 只支持在 uniapp vue3 项目中使用支持微信小程序和h5 (app端没有测试过)ui库用的 uview-plus省市区数据用的是 vant-ui 提供的一个赖库 vant/area-data 三、组件代码 <template><u-popup :show"show" type"botto…...

OpenCV报错:AttributeError: module ‘cv2.cv2‘ has no attribute ‘SIFT_create‘

报错位置&#xff1a; sift cv2.SIFT_create()报错原因&#xff1a;opencv将SIFT等算法整合到xfeatures2d集合里面了。 改为&#xff1a; sift cv2.xfeatures2d.SIFT_create()...

通用监控视频web播放方案

业务场景 对接监控视频&#xff0c;实现海康大华等监控摄像头的实时画面在web端播放 方案一&#xff0c;使用 RTSP2webnode.jsffmpeg 说明&#xff1a;需要node环境&#xff0c;原理就是RTSP2web实时调用ffmpeg解码。使用单独html页面部署到服务器后&#xff0c;在项目中需要播…...

C++基础知识3

1、为什么构造函数不能是虚构造&#xff1f; 虚函数对应一个虚表vtale&#xff0c;这个表的地址是存储在对象的内存空间的。如果将构造函数设置为虚函数&#xff0c;就需要到虚表中调用&#xff0c;但这时候对象没有实例化&#xff0c;没有内存分配&#xff0c;虚表就不存在&am…...

【配置vscode编写python代码并输出到外部控制台】

配置vscode编写python代码并输出到外部控制台 1、扩展中添加python插件 2、打开一个文件夹&#xff0c;在里面新建一个.py文件&#xff0c;粘贴print(‘你好啊&#xff01;’)并运行 运行结果如下: 3、点击调试点击如下图 生成launch.json&#xff0c;将console后面改成exte…...

RK3588开发笔记-MIPI-CSI接口视频解码芯片XS9922B调试

目录 前言 一、RK3588 MIPI接口介绍 二、xs9922B视频解码芯片介绍 三、原理图连接...

DVWA -xss

什么是XSS 跨站点脚本(Cross Site Scripting,XSS)是指客户端代码注入攻击&#xff0c;攻击者可以在合法网站或Web应用程序中执行恶意脚本。当wb应用程序在其生成的输出中使用未经验证或未编码的用户输入时&#xff0c;就会发生XSS。 跨站脚本攻击&#xff0c;XSS(Cross Site S…...

C语言编程实现只有一个未知数的两个多项式合并的程序

背景&#xff1a; 直接看题目把&#xff01;就是C语言写两个多项式多项式合并 题目要求&#xff1a; 1. 题目&#xff1a; 编程实现只有一个未知数的两个多项式合并的程序。如&#xff1a; 3x^26x7 和 5x^2-2x9合并结果为8x^24x16。 2. 设计要求 &#xff08;1&#xff09…...

C# .net创建一个MVC框架工程

二、C# .net创建一个MVC框架工程 1.步骤 首先打开VS &#xff0c;然后点击创建新项目 在三个选项框中输入我们需要的项目条件 最后一步创建完毕 创建会在资源解决方案生成如图&#xff1a;...

Deep learning of free boundary and Stefan problems论文阅读复现

Deep learning of free boundary and Stefan problems论文阅读复现 摘要1. 一维一相Stefan问题1.1 Direct Stefan problem1.2 Inverse Type I1.3 Inverse Type II 2. 一维二相Stefan问题2.1 Direct Stefan problem2.2 Inverse Type I2.3 Inverse Type II 3. 二维一相Stefan问题…...

LeetCode 1277. 统计全为 1 的正方形子矩阵【动态规划】1613

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

测试部门来了个00后卷王之王,老油条感叹真干不过,但是...

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。 这不&#xff0c;前段时间我们公司来了个00后&#xff0c;工作都没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了…...

360 G800行车记录仪,不使用降压线如何开机,8芯插头的定义。

G800记录仪的插头是这样的&#xff0c;图中标出了线的颜色。其中红色为常电V&#xff0c;黑色为GND负极&#xff0c;黄色为ACC受车是否启动控制。 这个记录仪原装的电源线没有降压功能&#xff0c;所以这里的V是12V。 记录仪内部有电源板&#xff0c;负责将12V降压为5V。 如果…...

vue2踩坑之项目:Swiper轮播图使用

首先安装swiper插件 npm i swiper5 安装出现错误&#xff1a;npm ERR npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: vue/eslint-config-standard6.1.0 npm ERR! Found: eslint-plugin-vue8.7.1 npm ERR! node_modules/esl…...

python经典百题之分桃子

题目:海滩上有一堆桃子&#xff0c;五只猴子来分。第一只猴子把这堆桃子平均分为五份&#xff0c;多了一个&#xff0c;这只 猴子把多的一个扔入海中&#xff0c;拿走了一份。第二只猴子把剩下的桃子又平均分成五份&#xff0c;又多了 一个&#xff0c;它同样把多的一个扔入海中…...

vscode ssh linux C++ 程序调试

vscode调试c++程序相比vs2022要复杂很多,vs2022可以"一键运行调试",vscode则需要自己配置。 ​vscode调试程序时,会在当前工作目录产生.vscode 目录, 该目录有两个重要文件launch.json和tasks.json, 下面介绍两种调试方法: 手动调试和自动调试。 手动调试 不管…...

VUE和Angular有哪些区别?

Vue.js和Angular是两个流行的前端JavaScript框架&#xff0c;它们有一些明显的区别&#xff0c;包括以下几个方面&#xff1a; 1、语言和工具链的选择&#xff1a; Vue.js使用HTML、JavaScript和CSS来创建组件&#xff0c;使得它更容易学习&#xff0c;因为它使用了常见的Web…...

云原生边缘计算KubeEdge安装配置(二)

1. K8S集群部署&#xff0c;可以参考如下博客 请安装k8s集群&#xff0c;centos安装k8s集群 请安装k8s集群&#xff0c;ubuntu安装k8s集群 请安装kubeedge cloudcore centos安装K8S 2.安装kubEedge 2.1 编辑kube-proxy使用ipvs代理 kubectl edit configmaps kube-proxy -…...

SQL多表设计--一对多(外键)

-- 完成部门和员工的-- 选择当前db03 这个数据库use db03;-- 查看当前选中的数据库select database();-- 创建员工表create table tb_emp (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32)…...

Stm32_标准库_9_TIM

频率(HZ)是频率的基本单位1HZ是1s的倒数 STM32F103C8T6一般情况给定时器的内部时钟都是72MHz&#xff08;系统主频率&#xff09; TIM基本构成 计数器、预分频器、自动化重装 // 都是16位其中计数器、自动化重装&#xff0c;都是16位换算成10进制范围为[0, 655536] 时间 1 /…...

终极指南:如何用Snipe-IT免费开源系统解决企业IT资产追踪难题

终极指南&#xff1a;如何用Snipe-IT免费开源系统解决企业IT资产追踪难题 【免费下载链接】snipe-it A free open source IT asset/license management system 项目地址: https://gitcode.com/GitHub_Trending/sn/snipe-it 想象一下&#xff0c;你的公司有500台笔记本电…...

使用Node.js和Taotoken构建一个简单的AI对话服务端

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 使用Node.js和Taotoken构建一个简单的AI对话服务端 基础教程类&#xff0c;面向Node.js后端开发者&#xff0c;讲解如何初始化一个…...

告别繁琐:Windows平台I2C总线高效调试实战

1. Windows平台I2C调试痛点解析 第一次在Windows下调试I2C设备时&#xff0c;我对着示波器抓到的杂乱波形发呆了整整两小时。与Linux系统自带i2c-tools的便利性相比&#xff0c;Windows环境确实像个"二等公民"——直到我发现CH341A这个神器。这个售价不到20元的USB转…...

挑战 100ms 延迟极限:深度拆解 dograh,构建企业级开源 WebRTC 实时语音智能体平台

发布日期&#xff1a; 2026-05-18标签&#xff1a; #VoiceAgent #WebRTC #语音智能体 #dograh #大模型 #实时音视频一、 引言在 2026 年&#xff0c;随着大模型多模态能力的爆发&#xff0c;传统的“打字输入、文字输出”交互模式正迅速向“纯语音实时对讲”演进。然而&#xf…...

HunterPie完全指南:如何在《怪物猎人世界》中获得实时数据监控优势

HunterPie完全指南&#xff1a;如何在《怪物猎人世界》中获得实时数据监控优势 【免费下载链接】HunterPie-legacy A complete, modern and clean overlay with Discord Rich Presence integration for Monster Hunter: World. 项目地址: https://gitcode.com/gh_mirrors/hu/…...

Laravel集成AI智能体:构建自主推理与行动能力的Web应用

1. 项目概述&#xff1a;当AI智能体遇见Laravel最近在GitHub上看到一个挺有意思的项目&#xff0c;叫adrenallen/ai-agents-laravel。光看名字&#xff0c;就能猜到个大概——这八成是把当下火热的AI智能体&#xff08;AI Agents&#xff09;能力&#xff0c;集成到经典的PHP框…...

低成本PHY芯片RTL8201F驱动移植实战:从LAN8742到RTL8201F的完整替换流程与验证

低成本PHY芯片RTL8201F驱动移植实战&#xff1a;从LAN8742到RTL8201F的完整替换流程与验证 在嵌入式以太网开发中&#xff0c;PHY芯片的选择往往需要在性能和成本之间取得平衡。当项目预算有限时&#xff0c;RTL8201F这类低成本PHY芯片就成为极具吸引力的选择。本文将详细介绍如…...

通过Nodejs快速为Web应用接入多模型AI能力

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过Nodejs快速为Web应用接入多模型AI能力 现代Web应用对智能交互能力的需求日益增长&#xff0c;无论是客服对话、内容辅助生成还…...

NotebookLM笔记导出全链路实操指南:从Chrome插件绕过限制到API直连导出(含Python脚本)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM笔记导出全链路概览 NotebookLM 是 Google 推出的基于用户上传文档构建个性化知识代理的 AI 工具&#xff0c;其核心价值在于语义理解与上下文生成&#xff0c;但原生不提供直接导出原始笔记…...

终极Windows虚拟手柄驱动配置指南:5步快速上手ViGEmBus

终极Windows虚拟手柄驱动配置指南&#xff1a;5步快速上手ViGEmBus 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 想在Windows系统中轻松实现游戏控制器模拟…...