更新记录
1.0.0(2025-09-26) 下载此版本
初版
平台兼容性
uni-app(4.51)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
其他
多语言 | 暗黑模式 | 宽屏模式 |
---|---|---|
× | × | √ |
Yo Select Location 城市选择组件
一个基于 uni-app 的城市选择组件,支持页面跳转模式,完美兼容 H5、小程序、APP 三大平台。
📚 文档导航
- 📖 5分钟快速上手 - 快速集成指南
- 🎨 使用示例 - 各种使用场景示例
- 🔑 API Key配置指南 - 腾讯地图API配置
- 📋 项目概览 - 项目架构和技术特点
✨ 功能特性
- 🚀 页面跳转模式:点击后进入独立城市选择页面
- 🔍 智能搜索:支持城市名称模糊搜索
- 📍 热门城市:支持热门城市快速选择
- 🔤 字母索引:支持字母索引快速定位,滚动联动
- 📱 响应式设计:完美适配各种屏幕尺寸
- 🎨 高度自定义:可自定义样式和占位符文本
- 🌐 多平台支持:H5、微信小程序、支付宝小程序、百度小程序、字节跳动小程序、QQ小程序、APP
- ⚡ 性能优化:JSON数据加载,条件编译优化
- 🛠️ 错误处理:完善的错误处理和备用方案
🚀 快速开始
第一步:复制组件文件
将 uni_modules/yo-select-location
目录复制到你的 uni-app 项目的 uni_modules
目录下。
第二步:创建城市选择页面
在你的项目中创建 pages/city-select/city-select.vue
页面,直接复制以下完整代码:
<template>
<view class="city-select-container">
<!-- 搜索框 -->
<view class="search-container">
<input
v-model="searchKeyword"
placeholder="请输入城市名称"
class="search-input"
@input="onSearchInput"
/>
</view>
<!-- 热门城市 -->
<view v-if="showHotCities && hotCities.length > 0" class="hot-cities-section">
<view class="section-title">热门城市</view>
<view class="hot-cities">
<view
v-for="city in hotCities"
:key="city.id"
class="hot-city-item"
@click="selectCity(city)"
>
{{ city.name }}
</view>
</view>
</view>
<!-- 城市列表 -->
<scroll-view
class="city-list"
scroll-y
:scroll-into-view="scrollIntoView"
@scroll=""
>
<view
v-for="(group, index) in filteredCityGroups"
:key="group.letter"
:id="`letter-${group.letter}`"
class="city-group"
>
<view class="group-header">{{ group.letter }}</view>
<view
v-for="city in group.cities"
:key="city.id"
class="city-item"
@click="selectCity(city)"
>
{{ city.name }}
</view>
</view>
</scroll-view>
<!-- 字母索引 -->
<view class="letter-index">
<view
v-for="letter in letters"
:key="letter"
class="letter-item"
:class="{ active: currentLetter === letter }"
@click="scrollToLetter(letter)"
>
{{ letter }}
</view>
</view>
</view>
</template>
<script>
import { loadCityData, searchCities, getHotCities } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/city-data.js'
import { getCurrentCity, setTencentMapKey } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/location.js'
export default {
data() {
return {
searchKeyword: '',
cityGroups: [],
filteredCityGroups: [],
hotCities: [],
showHotCities: true,
letters: [],
currentLetter: '',
scrollIntoView: '',
tencentMapKey: ''
}
},
onLoad(options) {
// 获取页面参数
this.showHotCities = options.showHotCities !== 'false'
this.tencentMapKey = options.tencentMapKey || ''
// 配置API Key
if (this.tencentMapKey) {
setTencentMapKey(this.tencentMapKey)
}
this.initData()
},
methods: {
async initData() {
try {
// 加载城市数据
const cityData = await loadCityData()
this.cityGroups = cityData.groups
this.filteredCityGroups = this.cityGroups
this.letters = cityData.letters
this.hotCities = getHotCities()
// 尝试获取当前位置
if (this.tencentMapKey) {
try {
const currentCity = await getCurrentCity()
console.log('当前位置:', currentCity)
} catch (error) {
console.log('定位失败:', error.message)
}
}
} catch (error) {
console.error('数据加载失败:', error)
uni.showToast({
title: '数据加载失败',
icon: 'none'
})
}
},
onSearchInput() {
if (this.searchKeyword.trim()) {
const results = searchCities(this.searchKeyword)
this.filteredCityGroups = results
this.showHotCities = false
} else {
this.filteredCityGroups = this.cityGroups
this.showHotCities = true
}
},
selectCity(city) {
// 通过事件总线发送城市选择事件
uni.$emit('citySelected', city)
// 返回上一页
uni.navigateBack()
},
scrollToLetter(letter) {
this.scrollIntoView = `letter-${letter}`
this.currentLetter = letter
},
(e) {
// 根据滚动位置更新当前字母
// 这里可以添加更精确的字母检测逻辑
}
}
}
</script>
<style scoped>
.city-select-container {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #f5f5f5;
}
.search-container {
padding: 20rpx;
background-color: #fff;
border-bottom: 1rpx solid #eee;
}
.search-input {
width: 100%;
height: 80rpx;
padding: 0 20rpx;
border: 1rpx solid #ddd;
border-radius: 40rpx;
font-size: 28rpx;
}
.hot-cities-section {
background-color: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
}
.section-title {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.hot-cities {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.hot-city-item {
padding: 10rpx 20rpx;
background-color: #f0f0f0;
border-radius: 30rpx;
font-size: 26rpx;
color: #333;
}
.city-list {
flex: 1;
background-color: #fff;
}
.city-group {
margin-bottom: 20rpx;
}
.group-header {
padding: 20rpx;
background-color: #f8f8f8;
font-size: 24rpx;
color: #999;
font-weight: bold;
}
.city-item {
padding: 30rpx 20rpx;
border-bottom: 1rpx solid #f0f0f0;
font-size: 28rpx;
color: #333;
}
.city-item:active {
background-color: #f0f0f0;
}
.letter-index {
position: fixed;
right: 20rpx;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10rpx;
}
.letter-item {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #666;
border-radius: 50%;
}
.letter-item.active {
background-color: #007aff;
color: #fff;
}
</style>
第三步:配置页面路由
在 pages.json
中添加城市选择页面:
{
"pages": [
{
"path": "pages/city-select/city-select",
"style": {
"navigationBarTitleText": "选择城市"
}
}
]
}
第四步:配置腾讯地图API Key(可选)
获取API Key
- 访问 腾讯位置服务控制台
- 注册并登录账号
- 创建应用并获取API Key
配置方式
方式一:通过页面参数传递(推荐)
// 跳转时传递API Key
uni.navigateTo({
url: `/pages/city-select/city-select?tencentMapKey=${encodeURIComponent('YOUR_API_KEY')}`
})
方式二:全局配置
// 在应用启动时配置
import { setTencentMapKey } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/location.js'
// 设置API Key
setTencentMapKey('YOUR_API_KEY')
方式三:使用配置文件
// 复制 config-example.js 为 config.js 并填入您的API Key
import { TENCENT_MAP_CONFIG } from './config.js'
import { setTencentMapKey } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/location.js'
setTencentMapKey(TENCENT_MAP_CONFIG.key)
注意事项
- 如果不配置API Key,定位功能将不可用,城市选择功能也需要key
- 建议在H5环境下配置代理以避免跨域问题
- 小程序和APP环境需要在小程序后台和APP配置中添加相应的域名白名单
第五步:在页面中使用
<template>
<view>
<view class="city-select-trigger" @tap="openCitySelect">
<text v-if="selectedCity">{{ selectedCity.t }}</text>
<text v-else class="placeholder">请选择城市</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
selectedCity: null
}
},
onLoad() {
// 监听城市选择事件
uni.$on('citySelected', this.onCitySelected)
},
onUnload() {
// 移除事件监听
uni.$off('citySelected', this.onCitySelected)
},
methods: {
// 打开城市选择页面
openCitySelect() {
// 配置您的腾讯地图API Key
const tencentMapKey = 'YOUR_TENCENT_MAP_KEY_HERE'
uni.navigateTo({
url: `/pages/city-select/city-select?tencentMapKey=${encodeURIComponent(tencentMapKey)}`
})
},
// 城市选择完成
onCitySelected(city) {
this.selectedCity = city
console.log('选中的城市:', city)
}
}
}
</script>
使用方式
基本使用
- 在需要城市选择的地方添加触发器
- 点击触发器跳转到城市选择页面
- 通过事件总线监听城市选择结果
自定义触发器样式
<template>
<view class="custom-trigger" @tap="openCitySelect">
<text class="trigger-text">选择城市</text>
<text class="trigger-arrow">></text>
</view>
</template>
<style>
.custom-trigger {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
background-color: #fff;
border-radius: 10rpx;
}
</style>
🌐 平台支持
数据加载方式
平台 | 主要方案 | 备用方案 | 数据文件 |
---|---|---|---|
H5 | fetch API |
import 动态导入 |
city.data.json → index.city.data.js |
小程序 | uni.request |
require 静态导入 |
city.data.json → index.city.data.js |
APP | plus.io 文件系统 |
require 静态导入 |
city.data.json → index.city.data.js |
平台特性
- ✅ H5 平台:原生 fetch API,性能最佳
- ✅ 微信小程序:uni.request + DOM查询备用方案
- ✅ 支付宝小程序:uni.request 加载
- ✅ 百度小程序:uni.request 加载
- ✅ 字节跳动小程序:uni.request 加载
- ✅ QQ小程序:uni.request 加载
- ✅ APP平台:plus.io 文件系统,原生性能
📊 城市数据格式
数据来源
城市数据来源于 腾讯位置服务 API,包含全国 493 个城市的完整信息,数据准确可靠。
数据格式
{
v: 110100, // 城市编码
t: '北京市', // 城市名称
lng: '116.413383', // 经度
lat: '39.910924' // 纬度
}
数据特点
- 数据来源:腾讯位置服务 API
- 城市数量:493 个城市
- 数据字段:城市编码、名称、经纬度坐标
- 拼音索引:支持按拼音首字母分组和搜索
- 坐标精度:高精度经纬度坐标,支持地图定位
📁 文件结构
yo-select-location/
├── pages/city-select/
│ └── city-select.vue # 城市选择页面
├── static/data/
│ ├── city.data.json # 主要数据文件(腾讯位置API数据)
│ └── index.city.data.js # 备用数据文件(JS格式)
├── uni_modules/
│ └── yo-select-location/ # 组件文件
│ ├── components/
│ └── package.json
├── README.md # 项目说明
├── QUICK_START.md # 5分钟快速上手
├── USAGE_EXAMPLES.md # 使用示例
├── API_KEY_CONFIGURATION.md # API Key配置指南
└── config-example.js # 配置文件示例
🎯 事件说明
事件名 | 说明 | 回调参数 |
---|---|---|
citySelected | 城市选择完成时触发(通过事件总线) | city: 选中的城市对象 |
⚙️ 配置说明
1. 腾讯地图API Key配置
获取API Key
- 访问 腾讯位置服务控制台
- 注册并登录账号
- 创建应用并获取API Key
配置方式
方式一:通过页面参数传递(推荐)
// 跳转时传递API Key
uni.navigateTo({
url: `/pages/city-select/city-select?tencentMapKey=${encodeURIComponent('YOUR_API_KEY')}`
})
方式二:全局配置
// 在应用启动时配置
import { setTencentMapKey } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/location.js'
// 设置API Key
setTencentMapKey('YOUR_API_KEY')
方式三:使用配置文件
// 复制 config-example.js 为 config.js 并填入您的API Key
import { TENCENT_MAP_CONFIG } from './config.js'
import { setTencentMapKey } from '@/uni_modules/yo-select-location/components/yo-select-location/utils/location.js'
setTencentMapKey(TENCENT_MAP_CONFIG.key)
注意事项
- 如果不配置API Key,定位功能将不可用,但城市选择功能仍然正常
- 建议在H5环境下配置代理以避免跨域问题
- 小程序和APP环境需要在小程序后台和APP配置中添加相应的域名白名单
2. 数据文件配置
- 主要文件:
/static/data/city.data.json
(腾讯位置API数据) - 备用文件:
/static/data/index.city.data.js
- 文件格式:JSON 优先,JS 作为备用
- 数据来源:腾讯位置服务 API,包含 493 个城市信息
3. 页面路由配置
在 pages.json
中添加城市选择页面:
{
"pages": [
{
"path": "pages/city-select/city-select",
"style": {
"navigationBarTitleText": "选择城市"
}
}
]
}
4. 小程序域名配置
在微信小程序中,需要在 manifest.json
中配置域名白名单(如果使用网络请求):
{
"mp-weixin": {
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
}
}
🛠️ 注意事项
- 数据文件:确保
static/data/city.data.json
文件存在(腾讯位置API数据) - 页面路由:城市选择页面需要正确配置路由
- 事件监听:使用事件总线监听城市选择结果
- 样式自定义:触发器样式可以完全自定义
- 平台兼容:不同平台使用不同的数据加载方式
- 错误处理:包含完整的错误处理和备用方案
- 数据更新:如需更新城市数据,请使用腾讯位置服务 API 获取最新数据
📈 性能优化
- 条件编译:不同平台使用最优的加载方式
- JSON数据:文件更小,加载更快
- 备用方案:确保数据加载的可靠性
- 错误处理:完善的错误提示和降级处理
🔧 调试说明
开启调试模式
在浏览器开发者工具中查看控制台输出:
// 数据加载日志
H5平台使用fetch加载JSON文件
H5平台JSON数据加载成功: [城市数据]
// 滚动联动日志
滚动事件触发: {isSearching: false, scrollTop: xxx}
找到匹配字母: A
字母状态更新: {from: "", to: "A"}
常见问题排查
- 数据加载失败:检查文件路径和格式
- 滚动联动不准确:查看控制台调试日志
- 平台兼容问题:确认条件编译配置正确
📝 更新日志
v3.0.0 (最新)
- ✅ 完美支持 H5、小程序、APP 三大平台
- ✅ 优化数据加载方式,使用腾讯位置API数据
- ✅ 修复 APP 平台数据加载问题
- ✅ 优化微信小程序滚动联动
- ✅ 添加完善的错误处理和备用方案
- ✅ 性能优化和调试功能增强
- ✅ 数据源升级为腾讯位置服务 API,包含 493 个城市
v2.0.0
- 从弹层模式改为页面跳转模式
- 简化组件结构,提高性能
- 支持自定义城市选择页面路径
- 优化用户体验
🤝 贡献指南
欢迎提交 Issue 和 Pull Request 来帮助改进这个组件!
📚 相关文档
- 📖 5分钟快速上手 - 快速集成指南
- 🎨 使用示例 - 各种使用场景示例
- 🔑 API Key配置指南 - 腾讯地图API配置
- 📋 项目概览 - 项目架构和技术特点
- 📄 README.md - 完整项目文档
📄 许可证
MIT License