uni-app 在nvue页面中 list组件内放置video list有固定高度 上拉加载视频时卡住闪退

uni-app 在nvue页面中 list组件内放置video list有固定高度 上拉加载视频时卡住闪退

开发环境 版本号 项目创建方式
Windows 6.1 HBuilderX
产品分类:uniapp/App

PC开发环境操作系统:Windows

PC开发环境操作系统版本号:6.1

HBuilderX类型:正式

HBuilderX版本号:3.2.9

手机系统:Android

手机系统版本号:Android 10

手机厂商:华为

手机机型:pot-al00a

页面类型:nvue

打包方式:云端

项目创建方式:HBuilderX

### 示例代码:

```html
<list v-if="!isKong" [@loadmore](/user/loadmore)="loadmore" class="video-list" :show-scrollbar="false"  :style="{height:height}">
    <cell ref="items" style="width:750rpx;" v-for="(item,index) in list" :key="item.id">
        <view class="video-list-cell" :style="{'padding-top':index==0?'30rpx':''}">
            <view class="video-box">
                <view class="video_c">
                    <video 
                    @pause="pauses(index)" 
                    @ended="pauses(index)" 
                    :id="'video'+index" 
                    :src="item.videoSrc" controls class="video" 
                    v-if="!item.isZB||item.isPlay">
                    </video>
                </view>
                <view class="img-box" @click="plays(index)" v-if="!item.isPlay">
                    <image :src="item.img" mode="" class="poster"></image>
                    <image src="../../static/index/play.png" mode="" class="play"></image>
                </view>
            </view>

            <view class="txt" @click="goToDetail(item)">
                <text class="txt-c">{{item.title}}</text>
            </view>
            <view class="v_bottom">
                <text class="name">{{item.source}}</text>
                <text class="time name">{{item.date}}</text>
            </view>
        </view>
    </cell>
    <cell v-if="list.length>0"><uni-load-more :status="more"></uni-load-more></cell>
    <!-- <loading></loading> -->
</list>

操作步骤:

在nvue页面中,list组件中,放置是video list有固定高度,上拉加载视频时,卡住闪退。加载几次还可以,但是加载多了就卡住闪退。

预期结果:

更Vue页面一样,可以滚动长列表不卡顿闪退。

实际结果:

在nvue页面中,list组件中,放置是video list有固定高度,上拉加载视频时,卡住闪退。加载几次还可以,但是加载多了就卡住闪退。

bug描述:

在nvue页面中,list组件中,放置是video list有固定高度,上拉加载视频时,卡住闪退。加载几次还可以,但是加载多了就卡住闪退。 控制台出现: draw android view, exception:WX_RENDER_ERR_LAYER_OVERFLOWLayer overflow limit error: 24 layers! 卡住闪退是由video组件引起的。


更多关于uni-app 在nvue页面中 list组件内放置video list有固定高度 上拉加载视频时卡住闪退的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

你是仿抖音效果吗?如果不是可以使用recycle-list https://uniapp.dcloud.io/component/recycle-list

更多关于uni-app 在nvue页面中 list组件内放置video list有固定高度 上拉加载视频时卡住闪退的实战教程也可以访问 https://www.itying.com/category-93-b0.html


<cell-slot> 包含自定义组件时,在 Android 上有性能问题,我的包含自定义组件,还是不行

回复 1***@qq.com: 你可以先试下 看下效果

这个问题是典型的 nvuevideo 组件在长列表中的性能瓶颈。WX_RENDER_ERR_LAYER_OVERFLOW 错误表明超出了原生渲染的层级限制(默认24层),每个 video 组件都会创建复杂的原生渲染层,在 list 中快速累积导致崩溃。

核心解决方案是优化 video 组件的渲染和管理:

  1. 使用 recycle-list 替代 list(强烈推荐) recycle-listnvue 专为超长列表设计的组件,通过严格的单元格复用机制大幅减少内存占用。将 list 标签直接替换为 recycle-listcell 替换为 cell-slot。这是解决此类问题最根本的方法。

  2. 实现视频组件的懒渲染与销毁 在滚动列表中,同时存在多个 video 实例是主因。需要监听滚动,仅让可视区域内的1-2个视频处于真实渲染和播放状态。

    • 计算可视区域: 利用 listrecycle-list[@scroll](/user/scroll) 事件,结合 boundingClientRect 异步API,判断哪些 cell 处于屏幕内。
    • 条件渲染 videocell 的模板中,增加一个数据项(如 isInViewport)。只有 isInViewporttrue 时,才渲染真正的 video 组件。否则,仅展示封面图(poster)。上拉加载新数据时,新加入的 video 默认应处于未渲染状态。
    • 销毁非活跃视频:cell 滑出可视区域时,不仅要切换为封面图,最好能通过 v-if 彻底销毁 video 组件实例,释放原生资源。
  3. 优化 video 组件属性

    • 确保所有 video 标签都设置了正确的 poster(封面图)属性。这能在视频未播放时展示静态图,减少资源占用。
    • 非活跃视频应确保处于 paused 状态。你已有的 @pause@ended 事件处理是好的,需要确保滑出视口的视频能触发暂停。
  4. 检查并限制列表项高度 你已设置 list 有固定高度 :style="{height:height}",这很好。请确保每个 cell 的高度也是大致固定或可计算的,这有助于 recycle-list 进行高效回收。避免 cell 内存在高度动态变化极大的内容。

  5. 分页加载策略 虽然你已有上拉加载,但建议设置一个最大列表项数量上限(例如100条)。加载更多时,可以移除最早期的部分项(如移除前20条),而不是无限累积。这在内容流场景中是常见做法,能从根本上控制内存增长。

代码调整方向示例(基于 recycle-list 和懒渲染思路):

<recycle-list v-if="!isKong" [@loadmore](/user/loadmore)="loadmore" class="video-list" :show-scrollbar="false" :style="{height:height}" [@scroll](/user/scroll)="handleScroll">
  <cell-slot v-for="(item,index) in list" :key="item.id">
    <view class="video-list-cell">
      <view class="video-box">
        <!-- 关键:根据计算出的 isInViewport 条件渲染 video -->
        <view class="video_c" v-if="item.isInViewport && (!item.isZB || item.isPlay)">
          <video 
            @pause="pauses(index)" 
            @ended="pauses(index)" 
            :id="'video'+index" 
            :src="item.videoSrc" 
            controls 
            class="video"
            :poster="item.img" <!-- 确保设置封面 -->
          ></video>
        </view>
        <!-- 非可视区域或未播放时,只显示封面图 -->
        <view class="img-box" v-else @click="plays(index)">
            <image :src="item.img" mode="" class="poster"></image>
            <image src="../../static/index/play.png" mode="" class="play"></image>
        </view>
      </view>
      <!-- ... 其他文本内容 ... -->
    </view>
  </cell-slot>
  <cell v-if="list.length>0"><uni-load-more :status="more"></uni-load-more></cell>
</recycle-list>
回到顶部