{{ key }}
{{ item.name }}
{{ item }}
{{ item2 }}
先上效果图

样式采用elementplus,各个组件详情查看elementplus官网
整体采用popover作弹出框,需要注意的是elementplus,使用插槽的方式,标题一个在popover里的reference具名插槽,插槽内部我们添加标题和下拉图标
下拉图标采用arrowdown(该图标为elementplus图标库封装后的,自己的项目请按照elementplus官网的用法),class通过visible控制样式,如果弹出框可见,代表此时已经下拉,将下拉箭头改为上拉
触发弹框的标题
icon样式部分
// 下拉旋转180度即可改为上拉
.rotate {
transform: rotate(180deg);
}
// 图标转动的时候设置0.25s的动画效果
svg {
width: 1em;
height: 1em;
transition: all 0.25s linear;
}
按城市和按省份分类采用radio单选框,下拉+搜索框采用select和option
字母部分根据数据渲染即可,具体内容采用scrollbar包裹
最终选择到具体城市,触发自定义事件传递数据,并将选择的城市渲染到页面上
关于点击字母跳转到对应城市
如果使用a链接的话,会导致路由改变,不合适,所以采用操作dom的方式,我们给每块数据绑定一个id属性
{{ key }}:
{{ item.name }}
接下来通过scrollIntoView跳转即可
// 点击字母,参数为点击的字母
let clickChat = (item: string) => {
// 获取dom中的这个字母id
let el = document.getElementById(item)
// 跳转到对应位置
if (el) el.scrollIntoView()
}
下拉框搜索
开启el-select组件的自定义搜索功能
过滤函数
数据拍平后过滤,将结果返回options用于渲染
由于数据的原因,按城市时可以同时实现中英文过滤,按省份则只能中文过滤
let filterMethod = (val: string) => {
searchValue.value = val
let values = Object.values(cities.value).flat(2)
if (val == '') {
options.value = values
} else {
if (radioValue.value === '按城市') {
// 中英文一起过滤
options.value = values.filter((item) => {
return item.name.includes(val) || item.spell.includes(val)
})
} else {
// 中文过滤
options.value = values.filter((item) => {
return item.name.includes(val)
})
}
}
}
chooseCity.vue
{{ result }}
{{ key }}
{{ key }}:
{{ item.name }}
{{ item }}
{{ item1.name }}:
{{ item2 }}
types.ts
export interface City {
id: number,
// 拼音
spell: string,
// 名字
name: string
}
export interface Province {
name: string,
data: string[],
id?: string
}
城市数据
支持首字母+拼音+省份搜索城市数据: 支持首字母+拼音+省份搜索城市数据 (gitee.com)## vue3+ts封装chooseCity