小程序實現帶索引的城市列表

本文實例為大傢分享瞭小程序實現帶索引的城市列表的具體代碼,供大傢參考,具體內容如下

效果

網上找的很多的效果右邊的索引不會按左邊滑動區域高亮處理所以自己寫瞭個

代碼實現

因為我的城市數據沒有而項目裡先有的是省市區代碼數據所以要先處理一下數據
用來獲取首字母:

//用來獲取首字母
import py from '../../utils/strChineseFirstPY'
checkCh(ch) {
      let uni = ch.charCodeAt(0);
      //如果不在漢字處理范圍之內,返回原字符,也可以調用自己的處理函數
      if (uni > 40869 || uni < 19968) {
        return ch;
      } //dealWithOthers(ch);
      //檢查是否是多音字,是按多音字處理,不是就直接在strChineseFirstPY字符串中找對應的首字母
      return (py.oMultiDiff[uni] ? py.oMultiDiff[uni] : (py.strChineseFirstPY.charAt(uni - 19968)));
    }

利用首字母講城市數據整理:

//用來獲取首字母
/**
     * @name: 
     * @test: test font
     * @msg: 
     * @param {*} data 數組
     * @param {*} field 依據那個字段排序
     * @return {*}
     */
    data_letter_sort (data, field) {
      let list = new Array();
      let letter = ''
      for (let i = 0; i < data.length; i++) {
        // 首字母 轉 大寫英文
        letter = (data[i][field]).substr(0, 1).toUpperCase();
        // 創建 字母 分組
        if (!(letter in list)) {
          list[letter] = new Array();
        }
        // 字母 分組 添加 數據
        list[letter].push(data[i]);
      }
       // 轉換 格式 進行 排序;
      let resault = new Array();
      for (let key in list) {
        resault.push({
          letter: key,
          list: list[key]
        });
      }
      resault.sort(function (x, y) {
        return x.letter.charCodeAt(0) - y.letter.charCodeAt(0);
      });
      // 轉換 數據 格式
      let json_sort = {}
      for (let i = 0; i < resault.length; i++) {
        json_sort[resault[i].letter] = resault[i].list;
      }
      return json_sort;
    },

處理過後的數據為按首字母排序的一個對象

然後難點就在右邊的索引怎麼按照左邊的區域來進行高亮顯示
首先我想的是獲取每個字母距離上邊的高度然後頁面滑動時進行高度判斷

//獲取城市數據的首字母列表
for (let key in this.cityList) {
      let obj = {
        py: key,
        active: false
      }
      if (obj.py == 'A') {
        obj.active = true
      }
      wx.createSelectorQuery().select('#'+ key).boundingClientRect(function(rect){
        obj.top = rect.top     // 節點的上邊界坐標
      }).exec()
      //pylist是用來渲染右邊索引列表的
      this.pyList.push(obj);
    }
//滑動時間
scroll(e) {
      let scrollTop = e.target.scrollTop
      this.pyList.map(item => {
        if ((scrollTop - item.top)>-76) {
          this.pyList.map(item => {
          //active是用來是否高亮顯示
            item.active = false
          })
          item.active = true
          return
        }
      })
    },

整體代碼

<!--
 * @Descripttion: 
 * @version: 
 * @Author: Songtutu
 * @Date: 2021-04-06 10:30:36
 * @LastEditors: Songtutu
 * @LastEditTime: 2021-04-08 13:40:32
-->
<template>
  <div class="main">
    <div class="search">
        <div class="search-box">
          <img :src="imglist.map_search"/>
          <input placeholder="請輸入城市名稱" @focus="focus" :focus="true" v-model="search" type="digit" -splaceholdertyle="font-size:14px;color: rgba(0, 0, 0, 0.3);" confirm-type="search" @confirm='doSearch'/>
        </div>
      </div>
    <!-- 城市列表 -->
    <scroll-view scroll-y="true" scroll-with-animation="true" enable-back-to-top="true" class="city-list" @scroll="scroll" :scroll-top="scrollTop" v-show="searchList.length == 0">
      
      <div class="dw-box">
        <div>定位城市:{{city}}</div>
        <img :src="imglist.map_sx" @click="sx()"/>
      </div>
      <div :id='key' class="city-group" v-for="(value, key, index) in cityList" :key="index">
        <div  class="city-group-title">{{key}}</div>
        <div class="city-item" :id="i == value.length -1?key:''" v-for="(item, i) in value" :key="i">
          {{item.cityName}}
        </div>
      </div>
    </scroll-view>
    <div class="search-list" v-show="searchList.length != 0">
      <div class="city-item" v-for="(item, i) in searchList" :key="i">
        {{item.cityName}}
      </div>
    </div>
    <div class="py-box" v-show="searchList.length == 0">
      <div class="py-item" :class="item.active?'active':''" v-for="(item, index) in pyList" :key="index" @click="clickPy(item, index)">{{item.py}}</div>
    </div>
  </div>
</template>
<script>
import py from '../../utils/strChineseFirstPY'
import area from '../../utils/area1'
export default {
  data() {
    return {
      cityList: [],
      imglist: [],
      search:'',
      city: '',
      pyList: [],
      scrollTop: 0,
      searchList: []
    }
  },
  created() {
    let title = "選擇城市"
    let frontColor = "#000000"
    let backgroundColor = "#ffffff"
    wx.setNavigationBarTitle({
      title
    })
    wx.setNavigationBarColor({
      frontColor, //前景顏色值,包括按鈕、標題、狀態欄的顏色,僅支持 #ffffff 和 #000000,
      backgroundColor
    });
    const imgurl = "圖片根目錄"
    this.imglist = {
      map_search: `${imgurl}map_search.png`,
      map_sx: `${imgurl}map_sx.png`
    }
    area.region.map(item => {
      item.mallCityList.map(i => {
        this.cityList.push(i)
      })
    })
    this.cityList.map(item => {
      item.py = this.checkCh(item.cityName.charAt(0))
    })
    this.cityList = this.data_letter_sort(this.cityList, 'py')
    console.log(this.cityList)
  },
  mounted() {
    for (let key in this.cityList) {
      let obj = {
        py: key,
        active: false
      }
      if (obj.py == 'A') {
        obj.active = true
      }
      wx.createSelectorQuery().select('#'+ key).boundingClientRect(function(rect){
        obj.top = rect.top     // 節點的上邊界坐標
      }).exec()
      this.pyList.push(obj);
    }
  },
  methods: {
    focus() {
      if (!this.search) {
        this.searchList = []
      }
    },
    doSearch() {
      this.searchList = []
      for(let key in this.cityList) {
        this.cityList[key].map(item => {
          if (item.cityName.indexOf(this.search) != -1) {
            this.searchList.push(item)
          }
        })
      }
    },
    clickPy(item) {
      this.scrollTop = item.top - 44
    },
    scroll(e) {
      let scrollTop = e.target.scrollTop
      this.pyList.map(item => {
        if ((scrollTop - item.top)>-76) {
          this.pyList.map(item => {
            item.active = false
          })
          item.active = true
          return
        }
      })
    },
    sx() {
      this.getLocation()
    },
    /**
     * 定位授權
     */
    getLocation() {
      const that = this;
      //調用自帶位置獲取
      wx.getSetting({
        success(res) {
          if (!res.authSetting["scope.userLocation"]) {
            wx.authorize({
              scope: "scope.userLocation",
              success() {
                that.localDetail();
              },
              fail() {
                wx.showModal({
                  title: "提示",
                  content: "獲取當前位置需要授權哦~",
                  success(res) {
                    if (res.confirm) {
                      wx.openSetting({
                        success: res => {
                          if (res.authSetting["scope.userLocation"]) {
                            that.localDetail();
                          }
                        }
                      });
                    } else if (res.cancel) {
                    }
                  }
                });
              }
            });
          } else {
            that.localDetail();
          }
        }
      });
    },
    localDetail() {
      wx.getLocation({
        type: "gcj02", //返回可以用於wx.openLocation的經緯度
        success: function(res) {
          console.log(res)
        }
      });
    },
    /**
     * @name: 
     * @test: test font
     * @msg: 
     * @param {*} data 數組
     * @param {*} field 依據那個字段排序
     * @return {*}
     */
    data_letter_sort (data, field) {
      let list = new Array();
      let letter = ''
      for (let i = 0; i < data.length; i++) {
        // 首字母 轉 大寫英文
        letter = (data[i][field]).substr(0, 1).toUpperCase();
        // 創建 字母 分組
        if (!(letter in list)) {
          list[letter] = new Array();
        }
        // 字母 分組 添加 數據
        list[letter].push(data[i]);
      }
       // 轉換 格式 進行 排序;
      let resault = new Array();
      for (let key in list) {
        resault.push({
          letter: key,
          list: list[key]
        });
      }
      resault.sort(function (x, y) {
        return x.letter.charCodeAt(0) - y.letter.charCodeAt(0);
      });
      // 轉換 數據 格式
      let json_sort = {}
      for (let i = 0; i < resault.length; i++) {
        json_sort[resault[i].letter] = resault[i].list;
      }
      return json_sort;
    },
    checkCh(ch) {
      let uni = ch.charCodeAt(0);
      //如果不在漢字處理范圍之內,返回原字符,也可以調用自己的處理函數
      if (uni > 40869 || uni < 19968) {
        return ch;
      } //dealWithOthers(ch);
      //檢查是否是多音字,是按多音字處理,不是就直接在strChineseFirstPY字符串中找對應的首字母
      return (py.oMultiDiff[uni] ? py.oMultiDiff[uni] : (py.strChineseFirstPY.charAt(uni - 19968)));
    }
  }
}
</script>
<style scoped>
.search-list {
  margin-top: 68rpx;
  background: white;
  width: 100%;
  height: auto;
}
.active {
  width: 16px;
  height: 16px;
  background: #005F28;
  line-height: 16px;
  border-radius: 50%;
  color: white;
  text-align: center;
}
.py-box {
  width: 16px;
  text-align: center;
  height: auto;
  position: fixed;
  top: 142px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
  font-size: 14px;
  right:9px;
}
.search {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 99;
  background: white;
  padding-bottom: 8px;
}
.city-item {
  margin: 0 32px 0px 16px;
  height: 40px;
  line-height: 40px;
  font-size: 14px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.9);
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.city-list {
  background: white;
  height: 100vh;
  position: relative;
}
.city-list .city-group-title {
  position: sticky;
  top: 33px;
  width: 100%;
  font-size: 14px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
  padding: 0px 16px;
  height: 32px;
  line-height: 32px;
  background: #F5F5F5;
  box-sizing: border-box;
}
.main{
  min-height: 100vh;
  background: #F5F5F5;;
  padding-top: 6px;
}
.search-box {
  margin-top: 6px;
  margin: 0 auto;
  width: 343px;
  display: flex;
  height: auto;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 4px;
}
.search-box img {
  width: 16px;
  height: 16px;
  margin-top: 2px;
  margin-right: 4px;
}
.search-box input {
  height: 20px;
  font-size: 14px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.9);
  line-height: 20px;
}
.dw-box {
  margin-top: 32px;
  height: 44px;
  display: flex;
  line-height: 44px;
  padding: 0 16px;
  font-size: 14px;
  font-weight: 400;
  color: #005F28;

}
.dw-box div {
  flex: 1;
  text-align: left;
}
.dw-box img {
  margin-top: 14px;
  width: 16px;
  height: 16px;
}
</style>

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: