项目中有一个类似城市区域选择的需求,看了插件市场没有看到贴合的,所以本小菜鸟决定自己动手,仅以此篇文章记录心路历程,免得以后忘记了。
城市选择主要划分为省、市、区三个大级,区级下又有多个门店。原型页面大概如下:
????????页面主要分三列,省级列表页,市级列表页,区级列表及区级门店列,可滚动列表嘛~自然想到的是用scroll-view这个组件了,于是我二话不说呼呼就放了三个scroll-view上去,设置scroll-y、设置了固定高度,先定死数据看看效果,好家伙,滚动效果是有,但是却是整个页面一起滚动,没有达到我预期的三个列表单独滚动的效果,看了一下文档好像我使用方法没毛病啊,该设置的都设置了。那既然不是scroll-view层级的区域滚动问题,就是外层页面滚动导致的了,于是我给三个scroll-view嵌套进一个view里并固定设置view的高度,哈哈哈,大致问题就解决了。
? ? ? ? 下面就是优化细节了,因为城区选择列表上还有搜索框和其他的东西,直接定死列表高度不太理想,根据当前屏幕高度和列表距离顶部的高度的差值可以计算出屏幕剩余的可用高度给到列表。(对DOM进行操作要在实例挂载完成之后,所以计算操作我放在了mounted里),贴代码,代码中高度*2是因为要换算成rpx
mounted() {
//计算滚动视图高度,不固定高度的话,同一页面三列scrollView不会分开滚动
let _this = this
let height = ""
uni.getSystemInfo({
success: (systemInfo) => {
console.log('屏幕信息',systemInfo)
const screenHeight = systemInfo.screenHeight || 568;
const query = uni.createSelectorQuery()
query.select('#scrollView').boundingClientRect(res=>{
console.log('scrollView:',res)
let top = res.top || 234;
let subHeight = screenHeight - top;
_this.subHeight = subHeight *2;
}).exec()
}
})
},
? ? ? ? 接下来就是处理后端返的数据,数据格式大概是这样的
[
{
"provincial": "广东省",
"municipals": [{
"municipal": "深圳市",
"countys": [{
"count": "福田区",
"details": [{
"detail": "福田街",
"cName": "会展校区",
...
}]
},
{
"count": "龙华区",
"details": [{
"detail": "龙华街道",
"cName": "上塘校区",
...
}]
}
]
},
{
"municipal": "广州市",
"countys": [{
"count": "白云区",
"details": [{
"detail": "白云街道",
"cName": "白云校区",
...
}, ]
}]
}
]
}
]
我的大概思路就是抽离出以省、市、区三级列表组合成的数组,然后在template中循环渲染。
因为初始数据每一级属性名都不一样的,所以我定义了一个数组['provincial','municipals','countys']以便后面分离数据使用, 定义了当前层级活动数组[0,0,0],表示当前选中的是省级列表的第0个,市级列表的第0个,区级列表第0个,以此类推。。。
来不及解释了~上代码
//创建默认选中栏
createActives() {
let arr = [];
for (let i = 0; i < this.level; i++) {
arr.push(0);
}
this.actives = arr; // [0,0,0]
},
//格式化数组
createLevelData(data) {
let dt= [];
let levelKeys = this.levelKeys; //['provincial', 'municipals','countys']
for (let i = 0; i < this.actives.length; i++) {
if (i == 0) {
dt.push(data);
} else {
dt.push(this.createSubData(dt[i-1][this.actives[i-1]][levelKeys[i]]));
}
}
this.dataList = dt;
},
createSubData(data, key) {
return Array.isArray(data) ? data : [];
}
格式化后的数组大概是这样的
[
[
{
municipals:Array(2),
provincial:"广东省"
},
{...}
],
[
{
countys:Array(3),
municipal:"深圳市
},{...}
],
[
{
count:"福田区",
details:Array(10)
},{...}
],
]
数据处理好了接下来就是渲染页面了,上代码
<view id="scrollView" :style="{display: 'flex', height: subHeight+'rpx', width: '100%'}">
<scroll-view scroll-y v-for="(item,index) in dataList" :key="index" class="col-scoll-view provincial">
<view v-for="(subItem,subIndex) in item" :key="subIndex" class="list-item" @click.stop="changeType(subIndex, index)">
<view :class="['text', levelNames[index], {'active': actives[index]==subIndex}]">{{subItem[levelNames[index]]}}</view>
<view class="details" :style="{height: levelNames[index]=='count'&&actives[index]==subIndex?tabHeight*subItem.details.length+'rpx':0}">
<view v-for="(details, dIndex) in subItem.details" :key="dIndex" class="campus" @click.stop="changeCampu(details)">{{details.cName}}</view>
</view>
</view>
</scroll-view>
</view>
到这里就差不多结束了
|