uni-app 动态组件切换+swiper导致页面显示错误

uni-app 动态组件切换+swiper导致页面显示错误

示例代码:

以下代码为我复现的demo,不是实际代码,实际代码更为复杂
以下代码在浏览器中测不出来我说的效果,需要在真机或者手机模拟器中运行
在父组件中通过 component :is 实现动态切换组件

<view class="nav_item" v-for="tab in tabs" :key="tab.id"  
    :class="{  
        on: currentTab === tab.id  
    }"  
    :data-id="tab.id"  
    @click="changeTab(tab)"  
>{{ tab.text }}</view>  

<component ref='child' :is="currentComponents" ></component>  

import Activity from '/components/story/activity.vue';  
import Everyone from '/components/story/everyone.vue';  
import Recommend from '/components/story/recommend.vue';  

const tab = [{  
            id: 'activity',  
            text: '活动',  
            component: Activity,  
        }.....]  
const currentTab = ref('recommend');  
const currentComponents = computed(() => tabs.find(tab => tab.id === currentTab.value).component);  
const changeTab = (tab) => {  
    currentTab.value = tab.id;  
}  

Activity 组件中

<view class="activity">  
    活动  
</view>  

Recommend 组件中

<swiper indicator-dots>  
    <swiper-item>  
        <view class="swiper-item">推荐 内容一</view>  
    </swiper-item>  
    <swiper-item>  
        <view class="swiper-item">推荐 内容二</view>  
    </swiper-item>  
</swiper>  

Everyone 组件中

<swiper indicator-dots>  
    <swiper-item>  
        <view class="swiper-item">大家 内容一</view>  
    </swiper-item>  
    <swiper-item>  
        <view class="swiper-item">大家 内容二</view>  
    </swiper-item>  
</swiper>  

操作步骤:

  1. Recommend 切换到Everyone
  2. Recommend 切换到Activity 再切换到Everyone

预期结果:

两个都正常

实际结果:

  1. 内容重叠,滑动轮播溢出容器隐藏
  2. 正常

bug描述:

在对组件切换时,如果当前组件和目标组件都存在swiper,就会报错“Uncaught TypeError: Cannot read property ‘children’ of null at uni-app-view.umd.js:7”,并且目标组件的swiper内容全部重叠在一起,对swiper左右切换时,不管是往左还是往右在css中都是translateX(100%),直接溢出容器外部隐藏。

如果目标组件不存在swiper或者当前组件不存在swiper,切换时正常显示。

如果在swiper里面内容复杂,比如再次嵌套swiper,组件切换时内容直接没有了

举例:

a(有swiper) -> b(有swiper) 报错,并且内容重叠,滑动轮播溢出容器隐藏
a(有swiper) -> c(无swiper) -> b(有swiper) 正常

解决方案:改成 v-show的方式(v-if 和 动态组件一样)或者其他方式实现 tab 栏切换

总结:我觉得是因为动态切换组件时,会卸载之前的组件,而之前组件中的swiper还在操作dom信息,由于组件已经卸载,所以是拿不到deom信息的,所以报错Uncaught TypeError: Cannot read property ‘children’ of null at uni-app-view.umd.js:7。而内容显示错误可能是因为swiper没有重新初始化。

如果我的总结不对欢迎各位大佬指点。希望官方尽早解决

信息类别 详细信息
产品分类 uniapp/App
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 Windows 11 专业版 24H2
HBuilderX类型 Alpha
HBuilderX版本号 4.63
手机系统 Android
手机系统版本号 Android 15
手机厂商 vivo
手机机型 iqoo neo8
页面类型 vue
vue版本 vue3
打包方式 云端
项目创建方式 HBuilderX

更多关于uni-app 动态组件切换+swiper导致页面显示错误的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app 动态组件切换+swiper导致页面显示错误的实战教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个典型的动态组件切换导致的Swiper组件状态异常问题。主要原因如下:

  1. 动态组件切换时(component:is),会销毁旧组件并创建新组件,导致Swiper实例被销毁但可能仍有未完成的DOM操作

  2. 当两个组件都包含Swiper时,切换过程中Swiper的销毁和初始化可能产生冲突,特别是当第一个Swiper的动画未完成时就切换到第二个Swiper时

解决方案建议:

  1. 使用v-show替代动态组件切换(已验证有效):
<Activity v-show="currentTab === 'activity'"/>
<Recommend v-show="currentTab === 'recommend'"/>
<Everyone v-show="currentTab === 'everyone'"/>
  1. 如果必须使用动态组件,可以在切换时强制销毁Swiper:
const changeTab = (tab) => {
  // 先重置currentComponents为null
  currentComponents.value = null
  nextTick(() => {
    currentTab.value = tab.id
  })
}
  1. 给每个Swiper添加唯一的key:
<swiper :key="'swiper-'+currentTab">
回到顶部