问题 : 在app 端直接使用会抖动
原因:
滚动抖动的根本原因是:
- 用户滚动页面
- onCardScroll 函数被频繁调用
- cardScrollTop 数据被更新
- scroll-view 的 :scroll-top 属性导致滚动位置被重新设置
- 形成循环,造成滚动不稳定和抖动
更改之后 还是有问题
- scroll-view 组件上有 scroll-top 属性绑定
- u-back-top 组件仍在使用 cardScrollTop 来控制显示/隐藏
- 当前的 handleBackToCardTop 方法无法真正滚动到顶部
问题原因
scroll-view 组件的 scroll-top 属性可能不会对相同值的变化做出响应,特别是当值已经是0时。通过先设置一个临时值(如-1),然后再设置为0,可以强制组件更新并执行滚动操作。
注意事项
- 确保已经安装了 lodash:
npm install lodash - 检查模板中是否正确绑定了 scroll-top:
:scroll-top="scrollTargetPosition" - 检查 u-back-top 组件是否正确绑定了
:scroll-top="displayScrollTop"(注意模板中似乎有多余的"s"字符,需要删除)
以下是完整实例
<template>
<view class="invite-new-user-page" ref='u-back-top'>
<u-navbar bgColor="transparent" leftIconColor="white" titleStyle="color:white" :autoBack="true">
</u-navbar>
<view class="inviter-main">
<view class="inviter-content" style="
background-image: url('xxxxx.jpg');
background-size: cover;
background-repeat: no-repeat;
">
<view class="inviter-card-part">
<view class="inviter-block">
<view class="invite-detail-btn-wrap">
<u--image width="100rpx" height="250rpx" src="xxx.png"
@click="toInviteRule"></u--image>
</view>
</view>
<scroll-view scroll-y class="invite-container" @scroll="onCardScroll" :scroll-top="scrollTargetPosition">
<view>
<!-- 战绩概览面板 -->
<!-- 列表 1:实名邀请 -->
<!-- 列表 2:认购奖励 -->
<!-- Modal -->
</view>
<u-back-top :scroll-top="displayScrollTop" :top="80" :custom="true" @click="handleBackToCardTop"></u-back-top>s
</scroll-view>
</view>
</view>
<view class="footer-btn">
<button class="footer-invite-btn" type="primary" @click="onAddCard">
xxxx
</button>
</view>
</view>
</view>
</template>
<script>
import { debounce } from 'lodash';
export default {
data() {
return {
displayScrollTop: 0, // 用于 back-top 组件显示/隐藏
scrollTargetPosition: 0, // 实际滚动目标位置
};
},
created() {
// 创建防抖函数
this.debouncedUpdateDisplayScroll = debounce((scrollTop) => {
this.displayScrollTop = scrollTop;
}, 100);
},
methods: {
// 监听卡片内部的滚动
onCardScroll(e) {
// 使用防抖更新显示用的滚动位置
this.debouncedUpdateDisplayScroll(e.detail.scrollTop);
},
// 点击按钮时,手动将 scrollTop 设为 0
handleBackToCardTop() {
this.scrollTargetPosition = -1;
this.$nextTick(() => {
this.scrollTargetPosition = 0;
});
},
},
};
</script>
<style lang="scss" scoped>
.invite-new-user-page {
height: 100vh;
width: 100%;
}
.inviter-main {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.inviter-content {
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
}
.inviter-card-part {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
padding: 20rpx;
position: relative;
}
.inviter-block {
width: 100%;
height: 480rpx;
background-color: #00000000;
position: relative;
}
.invite-detail-btn-wrap {
position: absolute;
right: -36rpx;
top: 220rpx;
z-index: 10;
}
.invite-container {
flex: 1;
overflow-y: scroll; // Use overflow-y for vertical scrolling
display: flex;
flex-direction: column;
background-color: #f3f3f3;
border-radius: 30rpx; // 15px -> 30rpx
}
.back-to-top {
position: fixed;
right: 20rpx;
bottom: 100rpx;
width: 80rpx;
height: 80rpx;
background-color: #007AFF;
/* 蓝色背景 */
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.3);
}
</style>