先说场景:类似于电影选座的场景,日期滑动 - 》 顶部的区域滑动 -》 下方的展示区域,三者皆可滑动;,下图预览效果;
三个区域都是可以滑动,日期的滑动可以带动右边的列表区域上下滑动;
上面的左右的滑动也可以带着下面的区域滑动;
区域的上下左右可以同时带着日期和区域上下左右滑动;
遇到的问题;H5滑动没有卡顿,APP就有卡顿和抖动;抖动很明显;
代码思路:设置left变量和top变量;
只要滑动列表,就把列表项和区域项往左;
往下滑同理;
等于说每滑动一次,上下左右滑动,都要赋值本地变量,然后靠这个本地变量来绑定在scroll-view上做设置;
代码:
<!-- 传递demo对象 -->
<view class="box">
<!-- 宴会厅名称 -->
<view class="top">
<scroll-view
scroll-x="true"
@scroll="scrollOn"
:scroll-left="scrollPosition"
scroll-with-animation="true"
>
<view class="tab" :style="{width:navWidth+'px'}">
<!-- 列表 -->
<view class="item iconfont" v-for="(tab,index) in list" :key="index">
{{tab.area_name}}
<!-- <span @click="deleteItem(index)" v-if="deleteShow"></span> -->
</view>
</view>
</scroll-view>
</view>
<!-- 日期列表 -->
<view class="left">
<scroll-view
:style="{height:windowHeight - 235 +'px'}"
scroll-y="true"
@scroll="ScrollTopOn"
:scroll-top="scrollTop"
>
<!-- 撑高度的白块 -->
<view class="date" style="height:35px;"></view>
<!-- 日期列表 -->
<view class="date" v-for="(item,index) in num" :key="index">{{month}}-{{index+1}}</view>
</scroll-view>
</view>
<!-- 列表 -->
<scroll-view
style="height:600px;"
scroll-x="true"
scroll-y="true"
@scroll="scrollOn"
:scroll-left="scrollPosition"
:scroll-top="scrollTop"
:style="{height:windowHeight - 235 +'px'}"
>
<view class="itemList" :style="{width:hotelWidth+'px'}">
<!-- 每一个li都是一列 -->
<view class="item" v-for="(main,mainIndex) in overList" :key="mainIndex">
<view
class="sonList"
:class="{active: son.y == mainIndex && son.x == index}"
v-for="(hotel,index) in main.revel_info"
:key="index"
@click="handelClickBuy(hotel,index,mainIndex)"
>
<view
class="topSon"
:class="{red:hotel.lunch_status == 2,purple:hotel.lunch_status == 1}"
v-if="hotel.revel_time != null && hotel.revel_time == index+1"
>午</view>
<view
class="bottomSon"
:class="{red:hotel.dinner_status == 2,purple:hotel.dinner_status == 1}"
v-if="hotel.revel_time != null && hotel.revel_time == index+1"
>晚</view>
<!-- <div class="allSon" v-if="hotel.dinner_status == 0 &&"></div> -->
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
// 点击son的x,y轴坐标
son: {
x: -1,
y: -1
},
num: 30,
navNum: 12,
navWidth: 0,
hotelWidth: 0,
scrollPosition: null,
scrollTop: null,
windowHeight: null,
deleteShow: true,
// 处理后的后端数据
overList: []
};
},
async mounted() {
// 返回附给nav尺寸
this.loadNavWidth();
// 计算年月
await this.computedYear();
// 对后端返回的数据做一层包装,使之能在模板中有着月份的长度正常渲染
this.overReturnList();
// 获取窗口高度
this.windowHeight = uni.getSystemInfoSync().screenHeight;
// 判断列表长度,设置删除键是否显示
if (this.list.length == 1) {
this.deleteShow = false;
return;
}
},
methods: {
// 点击看板列表
handelClickBuy(item, index, mIndex) {
// 拿到mIndex:通过minx拿到是第几个宴会厅
this.son.y = mIndex;
this.son.x = index;
// 向上提交
this.$emit("clickView", this.son);
},
// 删除一列
deleteItem(index) {
if (this.list.length == 2) {
this.deleteShow = false;
return;
}
this.overList.splice(index, 1);
this.list.splice(index, 1);
// 对宽度进行一个减少 navWidth && hotelWidth
this.navWidth = this.navWidth - 105;
this.hotelWidth = this.hotelWidth - 100; // 减去它们每一项的宽度
},
// 计算日期列表和view列表的上下滑动统一
ScrollTopOn(e) {
this.scrollTop = e.detail.scrollTop;
},
// 计算年月
computedYear() {
// 判断是否是闰年
if (
(this.year % 4 == 0 && this.year % 100 != 0) ||
this.year % 400 == 0
) {
// 闰年 2月29天
if ((this.month = 2)) {
this.num = 29;
this.overReturnList();
return;
}
} else {
// 平年
if (this.month == 2) {
this.num = 28;
this.overReturnList();
return;
}
}
if (
this.month == 1 ||
this.month == 3 ||
this.month == 5 ||
this.month == 7 ||
this.month == 8 ||
this.month == 10 ||
this.month == 12
) {
this.num = 31;
this.overReturnList();
return;
} else {
this.num = 30;
this.overReturnList();
return;
}
},
// 处理后端返回数据
overReturnList() {
uni.showLoading({
title: "解析看板数据中..."
});
// 遍历原数组个数
var overList = [];
var sliceList = JSON.parse(JSON.stringify(this.list)); // 深拷贝
if (sliceList.length == 0) {
return;
}
sliceList.map(v => {
// 构建arrayInfo
let arrayInfo = [];
// 默认添加的对象 (全部为空)
let dayObj = {
id: 1, // 有待商议
revel_time: null,
lunch_status: 0,
dinner_status: 0
};
// 出现的天数arr
let arr = [];
// 循环info的天数组成一个数组
for (let key in v.revel_info) {
// 序列化之后的字符串是 2019-04-09T02:20:58.601Z 需要拿到09这个天数
let showIndex = v.revel_info[key].revel_time.indexOf("-", 7);
// 切割字符串拿到天数,如果开头为0则去掉0,不为0直接被添加到数组中
var str = v.revel_info[key].revel_time.substr(showIndex + 1, 2);
if (str[0] != 0) {
arr.push(str);
} else {
arr.push(str[1]); // 添加天数
}
}
// 通过当前月份的天数来循环添加
for (let key = 0; key < this.num; key++) {
// 查询arr中的天数是否与当前循环的天数匹配
let num = arr.indexOf((key + 1).toString()); // 转成字符串进行查询
if (num != -1) {
// 如果当前循环的天数在arr中被找到,就不用添加空对象到数组中
v.revel_info[num].revel_time = v.revel_info[num].revel_time.substr(
v.revel_info[num].revel_time.indexOf("-", 7) + 1,
2
);
// 以上代码参考124行逻辑,就是切割字符串把天数附给revel_time在模板中展示出来
arrayInfo.push(v.revel_info[num]);
} else {
arrayInfo.push(dayObj); // 填充数组成功
}
}
// 拿到全部的对象,对象中的info就是我们要的内容
let obj = {
area_id: v.area_id,
area_name: v.area_name,
revel_info: arrayInfo
};
overList.push(obj);
});
this.overList = overList;
uni.hideLoading();
},
scrollOn(e) {
this.scrollPosition = e.detail.scrollLeft;
console.log(e.detail.scrollLeft);
if (e.detail.scrollTop == 0) {
return;
}
this.scrollTop = e.detail.scrollTop;
},
loadNavWidth() {
// 获取长度
this.navWidth = (85 * this.list.length) + 60;
// this.navWidth = `${navNum + 40}`; // nav与下方滑块兼容长度(60px不精准,但是能和下面滑块进行大致同步)
this.hotelWidth = (80 * this.list.length) + 40;
// this.hotelWidth = `${num + 10}`;
}
},
watch: {
year() {
this.computedYear();
},
month() {
this.computedYear();
},
list() {
this.loadNavWidth();
// 重新加载
this.overReturnList();
}
},
props: {
list: {
type: Array,
default: () => {
return [];
}
},
year: {
type: Number,
default: () => {
return 2019;
}
},
month: {
type: Number,
default: () => {
return 1;
}
},
viewFiexedScroll: {
typr: Boolean,
default: () => {
return false;
}
}
}
};
</script>
Kuo
我这边发现的问题是,滚动的同时设置了scrollTop导致的
2019-07-08 16:22
2019
回复 Kuo: 请问怎样解决这个问题?我也是这种情况,设置了scrollTop。
2020-05-07 18:12
3***@qq.com
回复 huawinner: 请问怎样解决这个问题?我也是这种情况,设置了scrollTop
2020-10-28 15:41
7***@qq.com
回复 Kuo: 谢谢亲
2021-04-17 14:39