城市选择组件说明文档

1. 组件概述

城市选择组件是一个基于 uni-app 框架开发的移动端城市选择页面,提供城市搜索、热门城市快速选择、字母索引定位等功能,为用户提供便捷的城市选择体验。

2. 功能特性

特性描述
🔍 城市搜索支持按城市名称、拼音、首字母三种方式搜索
热门城市展示热门城市快捷选择入口
📚 字母索引右侧字母索引栏,点击快速定位到对应字母区域
🎯 定位模拟模拟定位功能,一键获取当前城市
选中高亮选中城市名称高亮显示,提升用户体验
📱 响应式设计适配多种移动端屏幕尺寸

3. 技术栈

  • 框架: uni-app (Vue 3 + TypeScript)
  • 组件库: uView Plus
  • 样式: SCSS
  • 开发工具: HBuilderX

4. 项目结构

CityList_Demo/
├── pages/
│   └── index/
│       └── index.vue          # 城市选择主页面
├── utils/
│   └── cities.js              # 城市数据(热门城市、字母分组城市、字母列表)
├── uni_modules/
│   └── uview-plus/            # uView Plus 组件库
├── App.vue                    # 应用入口组件
├── main.js                    # 应用入口文件
├── manifest.json              # 应用配置
├── pages.json                 # 页面路由配置
└── uni.scss                   # 全局样式变量

5. 核心功能实现

5.1 数据结构

城市数据接口定义(CityItem):

字段类型描述
valuestring城市编码(如:110100 代表北京)
labelstring城市名称(如:北京市)
pinyinstring城市拼音(用于拼音搜索)

5.2 响应式状态

状态变量类型初始值说明
keywordref<string>''搜索关键词
selectedCityref<string>''用户选中的城市名称
currentCityref<string>'武汉市'当前定位城市
currentLetterref<string>''当前点击的字母索引
showLetterTipref<boolean>false是否显示字母提示弹窗
scrollToViewref<string>''滚动目标ID

5.3 核心函数

函数名功能说明参数返回值
handleSearch(val)搜索事件处理val: 搜索关键词
scrollToLetter(letter)点击字母索引滚动到对应区域letter: 目标字母
selectCity(city)选择城市处理city: 城市对象
refreshLocation()模拟刷新定位
onScroll()滚动事件处理(预留)

5.4 计算属性

属性名功能说明返回值
showSearchResult判断是否显示搜索结果boolean
searchList热门城市搜索结果Array
searchResult完整城市搜索结果(支持名称、拼音、首字母搜索)CityItem[]

6. 搜索算法说明

搜索功能支持三种匹配方式:

const searchResult = computed(() => {
    const keyword = keyword.value.toLowerCase().trim()
    if (!keyword) return []
    
    const results: CityItem[] = []
    
    for (const group of cityData) {
        for (const city of group.cities) {
            // 名称匹配
            const labelMatch = city.label.includes(keyword)
            // 拼音匹配
            const pinyinMatch = city.pinyin && city.pinyin.includes(keyword)
            // 首字母匹配
            const firstLetterMatch = city.label.charAt(0).toLowerCase() === keyword
            
            if (labelMatch || pinyinMatch || firstLetterMatch) {
                results.push(city)
            }
        }
    }
    
    return results.slice(0, 20)  // 最多返回20条结果
})

7. 字母索引滚动机制

点击右侧字母索引栏时,通过 scroll-viewscroll-into-view 属性实现滚动定位:

const scrollToLetter = (letter: string) => {
    currentLetter.value = letter
    showLetterTip.value = true
    scrollToView.value = ''
    
    setTimeout(() => {
        scrollToView.value = 'city-group-' + letter
    }, 50)
    
    setTimeout(() => {
        showLetterTip.value = false
    }, 500)
}

实现原理:

  1. 更新当前字母状态并显示提示弹窗
  2. 先清空滚动目标(触发重新滚动)
  3. 50ms 后设置滚动目标为对应字母区域的 ID
  4. 500ms 后隐藏字母提示弹窗

8. 样式结构

8.1 布局架构

```
┌─────────────────────────────────────────────────────┐
│  ┌─────────────────────────────────────────────┐    │
│  │           搜索栏 (search-bar)               │    │
│  └─────────────────────────────────────────────┘    │
│                                                      │
│  ┌─────────────────────────────────────────────┐    │
│  │    当前城市: 武汉市        [刷新定位]        │    │
│  │           (city-top-bar)                    │    │
│  └─────────────────────────────────────────────┘    │
│                                                      │
│  ┌─────────────────────────────────────┐  ┌───────┐ │
│  │  [搜索结果区域 / 城市列表区域]       │  │ A     │ │
│  │  • 热门城市                          │  │ B     │ │
│  │    北京 | 上海 | 广州 | ...         │  │ C     │ │
│  │  • 字母分组                          │  │ ...   │ │
│  │    A                                 │  │ Z     │ │
│  │      阿坝藏族羌族自治州              │  └───────┘ │
│  │      安康市                          │            │
│  │    B                                 │            │
│  │      蚌埠市                          │            │
│  │      ...                             │            │
│  └─────────────────────────────────────┘            │
│                                                      │
│  [字母提示弹窗: 居中显示当前字母]                      │
└─────────────────────────────────────────────────────┘


### 8.2 样式类说明

| 样式类 | 说明 | 关键属性 |
|--------|------|----------|
| `.content` | 主容器 | 背景色 `#f5f5f5` |
| `.search-bar` | 搜索栏容器 | 内边距 `20rpx` |
| `.city-top-bar` | 顶部栏 | flex布局,两端对齐 |
| `.city-scroll` | 滚动容器 | 固定定位,占满剩余空间 |
| `.city-group-title` | 字母分组标题 | 背景色 `#F5F5F5`,灰色文字 |
| `.city-item` | 城市列表项 | 白色背景,底部边框 |
| `.check-icon-blue` | 选中勾选图标 | 蓝色 `#007AFF` |
| `.city-name-highlight` | 选中城市高亮 | 蓝色 `#007AFF`,加粗 |
| `.letter-index` | 字母索引栏 | 固定定位右侧,垂直排列 |
| `.letter-item` | 字母索引项 | 灰色文字,激活时变蓝 |
| `.letter-tip` | 字母提示弹窗 | 半透明背景,居中显示 |

## 9. 使用示例

### 9.1 页面路由配置

在 `pages.json` 中配置页面路由:

```json
{
    "pages": [
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "选择城市"
            }
        }
    ]
}

9.2 组件集成

在其他页面跳转至城市选择页面:

// 跳转至城市选择页面
uni.navigateTo({
    url: '/pages/index/index'
})

9.3 数据交互

城市选择后可通过状态管理或事件传递选中的城市信息:

const selectCity = (city: CityItem) => {
    selectedCity.value = city.label
    currentCity.value = city.label
    
    // 可在此处通过 uni.$emit 或状态管理传递数据
    // uni.$emit('citySelected', city)
    
    uni.showToast({
        title: '已选择:' + city.label,
        icon: 'none'
    })
}

10. 兼容性说明

平台支持状态说明
微信小程序✅ 支持完全兼容
支付宝小程序✅ 支持完全兼容
H5✅ 支持完全兼容
App✅ 支持完全兼容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值