注:h5是正常的,小程序存在此问题
代码功能就是一个选择城市的页面,最上方可以输入相关字符搜索城市,左边悬浮可以点击滚动到具体前缀的城市集合,也可以按住进行拖动同时滚动城市集合。
目前遇到一个很蛋疼的问题,当我执行搜索时,但发现对象数据是更新成功了的(即cityValue是已经更新过的),但是视图渲染一直存在bug。
比如我在最上方输入框中搜索 “宁” ,再搜索 “安”,然后视图渲染后的顺序就会乱掉并且存在无效数据的的渲染,但cityValue数据本身却是正确的。
具体的问题可以点击 操作录像 查看。
录像的链接地址:https://www.loom.com/share/9b4bbe86208a48d59b35d90db62aa06f
以下是的选择城市页面的全部代码,附件里也有压缩后的代码文件,可以直接复制运行。
全部代码:
<template>
<view class="container">
<scroll-view class="scroller">
<div class="searchDiv">
<input type="text" v-model="searchTxt" confirm-type="search" @confirm="doSearch" class="searchInput"
placeholder="请输入城市名、拼音或首字母查询">
</div>
<div v-for="(item,index) in cityValue" :key="index">
<div :class="'cityPrefix prefix_' index">{{index}}</div>
<div class="provinceCity" v-for="cityName in item" :key="index">
<div class="cityItem">{{cityName}}</div>
</div>
</div>
</scroll-view>
<div class="fixedPrefixBar" @touchmove.stop.prevent="disabledScroll">
<div @click="choicePrefix(index)"
:class="[prefix == index ? 'fixedPrefixBarItemChecked' : 'fixedPrefixBarItem']"
v-for="(item, index) in cityValue" :key="index" @touchmove.stop.prevent="disabledScroll"
@touchstart="touchstart($event)" @touchmove="touchmove($event)" @touchend="touchend($event)">
{{index}}
</div>
</div>
</view>
</template>
<script>
export default {
data() {
return {
prefix: 'A',
cityValue: {},
searchTxt: "",
fixedListTop: 0,
fixedItemHeight: 0,
isMove: false,
cityRawValue: {
'A': [
"安阳",
"安庆",
"鞍山",
"安康",
"安顺",
"阿克苏",
"阿拉尔",
"阿拉善",
"阿勒泰",
"阿里",
"阿坝",
"澳门",
],
'B': [
"北京",
"白银",
"白城",
"白山",
"巴中",
"巴彦淖尔",
"滨州",
"蚌埠",
"亳州",
"本溪",
"北海",
"百色",
"保定",
"宝鸡",
"包头",
"保山",
"毕节",
"巴音",
"博尔塔拉"
],
'C': [
"重庆",
"常州",
"常德",
"长沙",
"长治",
"长春",
"潮州",
"成都",
"滁州",
"池州",
"朝阳",
"崇左",
"郴州",
"承德",
"沧州",
"赤峰",
"昌吉",
"楚雄"
],
'D': [
"大连",
"大庆",
"大兴安岭",
"大同",
"东莞",
"东营",
"德阳",
"德州",
"达州",
"丹东",
"定西",
"大理",
"德宏",
"迪庆"
],
'E': [
"鄂州",
"鄂尔多斯",
"恩施",
],
'F': [
"抚顺",
"抚州",
"阜阳",
"阜新",
"佛山",
"防城港",
"福州",
],
'G': ["广州", "广元", "广安", "贵港", "贵阳", "桂林", "赣州", "固原", "甘孜", "甘南", "果洛"],
'H': [
"淮南",
"淮北",
"淮安",
"黄石",
"黄冈",
"黄山",
"河源",
"河池",
"衡阳",
"衡水",
"哈尔滨",
"哈密",
"呼和浩特",
"呼伦贝尔",
"惠州",
"鹤壁",
"菏泽",
"合肥",
"葫芦岛",
"贺州",
"怀化",
"鹤岗",
"黑河",
"邯郸",
"杭州",
"湖州",
"汉中",
"海口",
"海北",
"海西",
"海南",
"黄南",
"红河"
],
'J': [
"济源",
"济南",
"济宁",
"荆门",
"荆州",
"晋城",
"晋中",
"金昌",
"金华",
"江门",
"九江",
"吉安",
"吉林",
"揭阳",
"焦作",
"锦州",
"鸡西",
"佳木斯",
"嘉峪关",
"酒泉",
"嘉兴",
"景德镇",
],
'K': [
"开封",
"昆明",
"克拉玛依",
"喀什",
"克孜勒苏",
],
'L': [
"六安",
"六盘水",
"临沂",
"临沧",
"临汾",
"辽阳",
"辽源",
"丽水",
"丽江",
"泸州",
"乐山",
"洛阳",
"漯河",
"莱芜",
"聊城",
"柳州",
"来宾",
"连云港",
"娄底",
"兰州",
"陇南",
"吕梁",
"廊坊",
"龙岩",
"拉萨",
"临夏",
],
'M': [
"茂名",
"梅州",
"绵阳",
"眉山",
"马鞍山",
"牡丹",
],
'N': [
"南充",
"南阳",
"南宁",
"南京",
"南通",
"南昌",
"南平",
"宁波",
"宁德",
"内江",
"怒江",
],
'P': [
"平顶山",
"平凉",
"攀枝花",
"濮阳",
"盘锦",
"萍乡",
"莆田",
"普洱",
],
'Q': [
"清远",
"青岛",
"钦州",
"齐齐哈尔",
"七台河",
"庆阳",
"秦皇岛",
"衢州",
"泉州",
"曲靖",
"黔东南",
"黔南",
"黔西南"
],
'R': ["日照", "日喀则"],
'S': [
"上海",
"三门峡",
"三明",
"三亚",
"汕头",
"汕尾",
"韶关",
"深圳",
"遂宁",
"商丘",
"宿州",
"沈阳",
"苏州",
"宿迁",
"十堰",
"随州",
"邵阳",
"双鸭山",
"绥化",
"朔州",
"石家庄",
"绍兴",
"上饶",
"商洛",
"石嘴山",
"四平",
"松原",
],
'T': [
"天津",
"泰安",
"泰州",
"通辽",
"通化",
"铜川",
"铜仁",
"铜陵",
"铁岭",
"天水",
"太原",
"唐山",
"台州",
"吐鲁番",
],
'W': [
"武汉",
"武威",
"乌海",
"乌兰察布",
"乌鲁木齐",
"潍坊",
"威海",
"芜湖",
"梧州",
"无锡",
"温州",
"渭南",
"吴忠",
],
'X': [
"西昌",
"西安",
"西宁",
"新乡",
"新余",
"许昌",
"信阳",
"宣城",
"徐州",
"襄阳",
"孝感",
"咸宁",
"湘潭",
"忻州",
"邢台",
"咸阳",
"厦门",
"湘西",
"凉山",
"西双版纳"
],
'Y': [
"宜宾",
"宜昌",
"宜春",
"玉林",
"玉溪",
"阳江",
"阳泉",
"云浮",
"雅安",
"烟台",
"营口",
"盐城",
"扬州",
"岳阳",
"益阳",
"永州",
"伊春",
"运城",
"鹰潭",
"延安",
"榆林",
"银川",
"延边",
"伊犁",
"玉树"
],
'Z': [
"张家界",
"张掖",
"张家口",
"中山",
"中卫",
"珠海",
"湛江",
"肇庆",
"自贡",
"资阳",
"郑州",
"周口",
"驻马店",
"淄博",
"枣庄",
"镇江",
"株洲",
"舟山",
"漳州",
"昭通",
"遵义",
],
}
}
},
onReady() {
this.cityValue = this.cityRawValue;
this.getFixedPrefixBarHeight();
},
methods: {
touchstart(e) {
this.isMove = true;
},
touchmove(e) {
if (this.isMove) {
var _karr = Object.keys(this.cityValue);
var _DValue = parseInt((e.touches[0].clientY - this.fixedListTop) / this.fixedItemHeight);
if (_DValue > (_karr.length - 1) || _DValue < 0) {
return false;
} else {
this.choicePrefix(_karr[_DValue]);
}
}
},
touchend(e) {
this.isMove = false;
},
disabledScroll() {
return;
},
getFixedPrefixBarHeight() {
const self = this;
setTimeout(function() {
uni.createSelectorQuery().in(self).select(".fixedPrefixBar").boundingClientRect(data => {
self.fixedListTop = data.top;
}).exec();
uni.createSelectorQuery().in(self).select(".fixedPrefixBarItemChecked").boundingClientRect(
data => {
self.fixedItemHeight = data.height;
}).exec();
}, 100);
},
doSearch() {
this.cityValue = {};
for (var index in this.cityRawValue) {
var valid = false;
var _arr = [];
for (var _index in this.cityRawValue[index]) {
if (this.cityRawValue[index][_index].indexOf(this.searchTxt) != -1) {
valid = true;
_arr.push(this.cityRawValue[index][_index]);
}
}
if (valid) {
this.cityValue[index] = _arr;
}
}
console.log(Object.keys(this.cityValue));
},
choicePrefix(prefix) {
if (this.prefix != prefix) {
this.prefix = prefix;
uni.pageScrollTo({
selector: ".prefix_" prefix,
duration: 300
});
}
},
}
}
</script>
<style>
.container {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
}
.scroller {
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.cityPrefix {
padding-left: 30upx;
width: 100%;
height: 50upx;
line-height: 50upx;
background-color: #efefef;
color: #333;
font-size: 26upx;
}
.provinceCity {
width: 100%;
padding-left: 30upx;
padding-right: 30upx;
}
.cityItem {
width: 100%;
height: 100upx;
line-height: 100upx;
color: #333;
font-size: 30upx;
border-bottom: solid 1upx #efefef;
}
.fixedPrefixBar {
width: 60upx;
background-color: pink;
padding-left: 30upx;
display: flex;
position: fixed;
top: 160upx;
right: 0upx;
flex-direction: column;
}
.fixedPrefixBarItem {
width: 60upx;
height: 40upx;
line-height: 40upx;
padding-right: 30upx;
text-align: center;
font-size: 26upx;
color: #333333;
}
.fixedPrefixBarItemChecked {
width: 40upx;
text-align: center;
height: 40upx;
line-height: 40upx;
margin-left: 10upx;
border-radius: 20upx;
font-size: 26upx;
color: #ffffff;
background-color: #00CC00;
}
.searchDiv {
width: 690upx;
height: 65upx;
margin-left: 30upx;
margin-right: 30upx;
margin-bottom: 15upx;
margin-top: 15upx;
border-radius: 50upx;
background-color: #e7e7e7;
display: flex;
flex-direction: row;
align-items: center;
}
.searchIcon {
width: 30upx;
height: 30upx;
margin-right: 10upx;
margin-left: 115upx;
}
.searchInput {
width: 515upx;
height: 65upx;
line-height: 65upx;
text-align: left;
font-size: 26upx;
color: #666;
}
.locationTitle {
margin-left: 30upx;
color: #ccc;
font-size: 26upx;
}
.locationCity {
width: 230upx;
height: 65upx;
text-align: center;
line-height: 65upx;
margin-left: 30upx;
border-radius: 60upx;
border: solid 1upx #aaa;
font-size: 26upx;
color: #666;
margin-bottom: 20upx;
margin-top: 15upx;
}
</style>