直入主题,实现什么蛇皮东西呢?大概是这个样子:
![](https://img.haomeiwen.com/i18898003/e42efd69be47f29f.png)
点击右边字母表的某个字母能跳转,然后搜索:
![](https://img.haomeiwen.com/i18898003/68a2348465473b96.png)
先一步一步来,首先渲染出这个城市列表,为了方便而且中国的城市名称基本不会有变动,所以我直接把城市的数据全部写在一个对象里面导出,当然不可能手写,大家百度就可以拿得到,这里我提供一个:中国所有城市按拼音排序json文件
然后大家把这个文件的 cities对象整个复制出来,在你的小程序的某个js文件中:
![](https://img.haomeiwen.com/i18898003/2e3ccec42143a6bc.png)
然后在你要用的地方就可以引用:
import {citys} from '../../base/citys.js' // 你的路径
这样就可以得到全部城市的信息,然后去遍历,但是这个citys是个对象,在小程序中去wx:for一个对象,然后对象的每个属性才是数组,会是怎么样的呢?
其实就是跟遍历二维数组一样,进行双层遍历,然后区别我在下面再讲,先看代码:
<view wx:for="{{citys}}"
wx:for-index="key" // 重命名wx:for的索引
wx:for-item="value" // 重命名wx:for的循环项
wx:key="{{key}}">
<view id="{{key}}" class="search-title">{{key}}</view> // 每一组的标题也就是A、B、C...
<view wx:for="{{value}}"
wx:key="{{index}}"
class="item-label">
<text>{{item.name}}</text>
</view>
</view>
第一层循环是去循环对象,wx:for的索引名称默认是index,如果是去遍历对象,那这个索引就是对象的key,也就是ABCD,所以我将它改名为key,然后将每一个循环项的名称改为value,就是上面的每一个数组,第二层遍历就是正常的遍历数组,这样就可以遍历出整个城市列表。
- 接下来是右边的字母表
拿同样的数据去遍历就可以,这次只需要显示出对象的key就可以:
<view class="alphabet">
<view wx:for="{{citys}}"
wx:for-index="key"
wx:key="{{key}}"
class="alphabet-item"
catchtap="chooseCitys"
data-id="{{key}}">
{{key}}
</view>
</view>
接下来是实现点击字母表的字母跳转到列表的指定位置,看我上面的两段代码,在城市列表的每一组标题我给绑定了id,是用对象的key绑定,也就是A、B、C、D...,然后在字母表的每一个字母也绑定了自定义属性data-id,同样也是用key绑定,这样和上面的标题对应上,接下来就是实现。
首先我们要跳转到指定位置,超人鸭看了小程序的组件文档,发现了一个叫scroll-view的组件,这是它的部分属性:
![](https://img.haomeiwen.com/i18898003/1c25bc0f159ddd51.png)
我圈住的属性就是实现跳转的关键,传入一个元素id,就可以跳转到指定元素的位置,我们把城市列表都包裹中scroll-view组件里面,并写上相应属性:
<scroll-view scroll-y="true"
style="height:100%;"
scroll-into-view="{{id}}">
// 城市列表
</scroll-view>
这里需要注意的一个点是设置scroll-view组件的方向为纵向的时候需要为组件指定高度。
给scroll-into-view动态的绑定一个id,需要在data中定义id这个变量
然后在字母表的点击事件中改变这个id,记得我们上面给每个字母绑定了自定义属性data-id="{{key}}",在点击事件中可以拿到:
chooseCitys(event) { // 点击字母表跳转到指定的城市列表
const id = event.target.dataset.id
console.log(id)
this.setData({
id
})
}
这样就完成了点击字母表进行跳转的功能,接下来是搜索,回到一开始的城市列表数据,每个城市都有中文名和拼音,所以可以实现通过名称或者拼音实现搜索,这是搜索框:
<input class="search-input" placeholder="请输入城市中文名或拼音" bindinput="handleInput"></input>
然后先看我一开始贴的demo图,搜索之后,整个页面是显示搜索结果,我自己的实现方式是在原来的页面上加一个层,设置z-index遮住原来的页面,先看看wxml:
<view class="search-content" hidden="{{!isShow}}">
<scroll-view scroll-y style="height:100%;">
<view wx:for="{{searchCitys}}" wx:key="{{index}}">
<text>{{item.name}}</text>
</view>
<view wx:if="{{!searchCitys.length}}">没有匹配数据</view>
</scroll-view>
</view>
看看这一个view的样式:
.search-content{
position: absolute;
top: 110rpx; // 搜索框的高度
left: 0;
bottom: 0;
right: 0;
z-index: 3;
}
然后上面定义两个变量,一个是isShow控制这一层的出现与消失,第二个是searchCitys,也就是搜索出来的结果,都需要在data中定义,然后逻辑在input的输入事件中执行,上面定义了bindinput="handleInput"
handleInput(event){ // 输入框输入或改变事件
let value = event.detail.value // 获取输入框中的值
let list = [] // 临时变量
this.setData({
isShow: true // 显示
})
if(value == '') { // 如果清空输入框
this.setData({
isShow: false, // 隐藏
searchCitys: [] // 清空搜索结果
})
return // 不再往下执行(重要!)
}
for(let k in citys) { // 进行匹配,citys就是全部城市数据
citys[k].forEach((item) => {
if(item.spell.indexOf(value) != -1 || item.name.indexOf(value) != -1) {
list.push(item)
}
})
}
this.setData({
searchCitys: list // 赋值
})
}
这样就实现了搜索框一输入就会显示那一层搜索结果的页面,如果清空搜索结果就会自动隐藏,同时实现了搜索功能与提示:
![](https://img.haomeiwen.com/i18898003/585b16a32f119657.png)
这次超人鸭是在原来的功能上提炼出这个功能来写博文,代码也都是盲改,逻辑是没错的,但如果代码有错误或者有其他方法,欢迎指教哦。
网友评论