小程序中实现城市选择列表

直入主题,实现什么蛇皮东西呢?大概是这个样子:

image.png

点击右边字母表的某个字母能跳转,然后搜索:
image.png

先一步一步来,首先渲染出这个城市列表,为了方便而且中国的城市名称基本不会有变动,所以我直接把城市的数据全部写在一个对象里面导出,当然不可能手写,大家百度就可以拿得到,这里我提供一个:中国所有城市按拼音排序json文件
然后大家把这个文件的 cities对象整个复制出来,在你的小程序的某个js文件中:
image.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的组件,这是它的部分属性:


image.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  // 赋值
  })
}

这样就实现了搜索框一输入就会显示那一层搜索结果的页面,如果清空搜索结果就会自动隐藏,同时实现了搜索功能与提示:


image.png

这次超人鸭是在原来的功能上提炼出这个功能来写博文,代码也都是盲改,逻辑是没错的,但如果代码有错误或者有其他方法,欢迎指教哦。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,537评论 0 17
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,144评论 1 32
  • 6/18为爱坚持,亲子共读day30 昨晚他读了一面之后,要求我读给他听,我同意了。我读了两章灯塔之家系列之暴...
    曦哈小子阅读 216评论 0 0
  • “怀采薇。”音色如泠泠珠玉,温雅而疏离。 那男人细细咀嚼了几秒,像是要将三个字吞咽下去似的:“相顾无相识,长歌怀采...
    笑答君莫问阅读 398评论 0 0
  • 从量变到质变,这个引人深思的哲学话题。仔细想想,其实也与我们的生活息息相关,生活里其实也处处通透着这样的道理。 ...
    奥里给gkd阅读 974评论 0 0