小程序带索引城市列表
Song_Tutu 人气:0效果
网上找的很多的效果右边的索引不会按左边滑动区域高亮处理所以自己写了个
代码实现
因为我的城市数据没有而项目里先有的是省市区代码数据所以要先处理一下数据
用来获取首字母:
//用来获取首字母 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>
加载全部内容