uniapp scroll-view 页面滑动 抖动问题

33 阅读2分钟

问题 : 在app 端直接使用会抖动

原因:

滚动抖动的根本原因是:

  1. 用户滚动页面
  2. onCardScroll 函数被频繁调用
  3. cardScrollTop 数据被更新
  4. scroll-view 的 :scroll-top 属性导致滚动位置被重新设置
  5. 形成循环,造成滚动不稳定和抖动

更改之后 还是有问题

  1. scroll-view 组件上有 scroll-top 属性绑定
  2. u-back-top 组件仍在使用 cardScrollTop 来控制显示/隐藏
  3. 当前的 handleBackToCardTop 方法无法真正滚动到顶部

问题原因

scroll-view 组件的 scroll-top 属性可能不会对相同值的变化做出响应,特别是当值已经是0时。通过先设置一个临时值(如-1),然后再设置为0,可以强制组件更新并执行滚动操作。

注意事项

  1. 确保已经安装了 lodash:npm install lodash
  2. 检查模板中是否正确绑定了 scroll-top:scroll-top="scrollTargetPosition"
  3. 检查 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>