uni-app nvue中绑定key后还是无法保留滚动条位置

uni-app nvue中绑定key后还是无法保留滚动条位置

开发环境 版本号 项目创建方式
Windows win10 HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Windows

HBuilderX类型:正式

HBuilderX版本号:3.1.22

手机系统:Android

手机系统版本号:Android 10

手机厂商:华为

手机机型:HONOR X10

页面类型:nvue

打包方式:云端

示例代码:

<view class='content'>  
    <scroll-view class="box" ref='box' :scroll-y="true" @scrolltoupper='onScrolltoupper'>  
        <view class="btn" v-for="(item,index) in lists" :key='item.id'>  
            {{item.name}}  
        </view>  
    </scroll-view>  
    <view class="btn" @tap='onAdd' style="background-color: #0071FF;margin-top: 100rpx;">  
        添加  
    </view>  
</view>  
export default{  
    data(){  
        return{  
            lists:[  
                {name:'这是个1',id:1},  
                {name:'这是个2',id:2},  
                {name:'这是个3',id:3},  
                {name:'这是个4',id:4},  
                {name:'这是个5',id:5},  
                {name:'这是个6',id:6},  
                {name:'这是个7',id:7},  
                {name:'这是个8',id:8},  
                {name:'这是个9',id:9},  
                {name:'这是个10',id:10}  
            ],  
            num:0,  
            top:0  
        }  
    },  
    methods:{  
        onAdd(){  
            this.lists.unshift({  
                    "name": "兔兔"+this.num,  
                    "id":this.lists.length+1  
                });  
            this.num++;  
            console.log(this.lists)  
        },  
    }  

}
.btn{  
    width: 750rpx;  
    height: 100rpx;  
    background: yellow;  
    margin-top: 20rpx;  
    display: flex;  
    align-items: center;  
    justify-content: center;  
    font-size: 30rpx;  
    font-weight: bold;  
}  
.content{  
    width: 750rpx;  
    height: 100vh;//nvue中改成flex: 1;  
    background-color: pink;  
    display: flex;  
    flex-direction: column;  
}  
.box{  
    width: 750rpx;  
    height: 800rpx;  
    background-color: blue;  
}  
.sec{  
    width: 750rpx;  
    height: 100%;  
    background-color: red;  
}

操作步骤:

逐步复制以上代码,将滚动条滚之中间,点击添加按钮来添加数据。

预期结果:

保留滚动条位置,不会因为插入数据产生蠕动效果。

实际结果:

在安卓系统的vue文件中是有效的,列表并不会产生蠕动且保留滚动条原有位置,但是ios的vue,nvue,以及安卓的nvue文件都会蠕动,滚动条位置随着插入不断往下滚动。

bug描述:

使用vue中使用scroll-view组件,只要绑定key值,中途插入(unshift)数据,滚动条仍然会保留插入之前的位置,不会主动往下蠕动(ios中无效); 但是在Nvue中无论是IOS还是安卓都无效,插入数据会一直蠕动。


更多关于uni-app nvue中绑定key后还是无法保留滚动条位置的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app nvue中绑定key后还是无法保留滚动条位置的实战教程也可以访问 https://www.itying.com/category-93-b0.html


在 nvue 中,即使为列表项设置了 :key,使用 unshift 插入数据时,滚动位置仍然会发生变化,这是 nvue 与 vue 页面在渲染机制上的一个已知差异。

nvue 基于原生渲染,其列表的复用机制与 vue 页面中的虚拟 DOM 不同。当数据变化触发列表更新时,原生端会尝试复用已有的原生视图组件。然而,在列表头部插入新项时,为了优化性能,原生渲染引擎可能会重新计算布局,导致整个列表的渲染位置发生偏移,从而表现为滚动条“蠕动”。

针对你的场景,可以尝试以下方案:

  1. 使用 scroll-top 手动控制位置:在插入数据前,记录当前的滚动位置 scrollTop。在数据更新后的下一个渲染周期(如使用 this.$nextTick),将 scrollTop 设置回原来的值,并加上新插入项的高度(本例中为 120rpx,即 100rpx 高度 + 20rpxmargin-top)。

    onAdd() {
        // 1. 获取当前滚动位置
        const scrollTop = this.top; // 需要在scroll事件中更新this.top
        // 2. 插入数据
        this.lists.unshift({
            "name": "兔兔" + this.num,
            "id": this.lists.length + 1
        });
        this.num++;
        // 3. 在下个渲染周期重置滚动位置
        this.$nextTick(() => {
            // 计算新的滚动位置:原位置 + 新增项的高度
            // 注意:在nvue中,scroll-top的单位是px,如果设计稿是rpx,需要转换
            // 假设设计稿宽度750rpx,可以这样转换:const newScrollTop = scrollTop + uni.upx2px(120);
            const newScrollTop = scrollTop + 120; // 这里假设scrollTop和高度单位一致,请根据实际情况调整单位
            this.top = newScrollTop;
        });
    }
回到顶部