uni-app Vite+Vue3抖音小程序组件使用v-if引发的BUG

发布于 1周前 作者 eggper 来自 Uni-App

uni-app Vite+Vue3抖音小程序组件使用v-if引发的BUG

产品分类

uniapp/小程序/字节跳动

PC开发环境操作系统

Windows

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

Windows 10 专业版 22H2

第三方开发者工具版本号

4.2.1

基础库版本号

3.16.0.0

项目创建方式

CLI

CLI版本号

3.0.0-3081220230817001

示例代码

<template>  
  <view>  
    <PopupNew :show="showPopup">  
      <view>Ni Hao</view>  
    </PopupNew>  
    <button @click="showPopup = !showPopup">切换</button>  
  </view>  
</template>  

<script setup lang="ts">  
import { ref } from 'vue';  
import PopupNew from '@/components/PopupNew.vue';  

const showPopup = ref(false);  
</script>
<template>  
  <view v-if="show" key="1">  
    <slot />  
  </view>  
</template>  

<script setup lang="ts">  
defineProps({  
  show: { type: Boolean, default: false }  
});  
</script>

操作步骤

进入如上代码页面, 点击切换按钮, 对子组件进行一轮可见度切换, 由隐藏切换为可见, 再由可见切换为隐藏, 最后再切换到显示状态, 此时观察抖音开发者工具的调试器的Elements, 会发现子组件的v-if所在view, 重复的挂载了一个, 这样在不断的可见度切换后, 会创建很多很多的view元素

预期结果

毫无疑问, 在v-if 的条件为false时, 应该完全卸载v-if所在的dom元素才是, 再重新可见后重新挂载dom元素

实际结果

然而目前的情况是v-if条件为false, 其所在dom并未被销毁

bug描述

在打包成抖音小程序后, 通关开发者工具的调试器发现, 子组件通过v-if切换显示的情况下, 反复的切换可见度, 会导致组件内的dom元素重复的创建, 在一轮可见切换后, 总会多出一个dom元素


4 回复

感谢反馈,已复现该问题 暂时直接在父组件那里直接使用v-if解决 <PopupNew v-if="showPopup">
<template>
<view>Ni Hao</view>
</template>
</PopupNew>


感谢跟踪, 期待修复!

进一步排查,发现是抖音小程序官方那边的问题,用原生抖音小程序语言在自定义组件里面使用的tt:if时,组件不会自动销毁,需要去抖音小程序官方社区进行反馈

在使用 uni-app + Vite + Vue3 开发抖音小程序时,使用 v-if 可能会引发一些 BUG。以下是一些可能的原因和解决方案:

1. v-ifv-for 的优先级问题

  • 问题描述: 在 Vue3 中,v-if 的优先级高于 v-for,而在 Vue2 中则相反。如果你在同一个元素上同时使用 v-ifv-for,可能会导致渲染错误。
  • 解决方案: 避免在同一个元素上同时使用 v-ifv-for。可以将 v-if 放在外层元素上,或者使用计算属性来过滤数据。
<!-- 不推荐 -->
<div v-for="item in items" v-if="item.visible">
  {{ item.name }}
</div>

<!-- 推荐 -->
<div v-for="item in visibleItems" :key="item.id">
  {{ item.name }}
</div>

<script>
export default {
  computed: {
    visibleItems() {
      return this.items.filter(item => item.visible);
    }
  }
}
</script>

2. v-ifkey 的配合问题

  • 问题描述: 在使用 v-if 时,如果组件的 key 没有正确设置,可能会导致组件状态未正确重置或复用。
  • 解决方案: 确保在使用 v-if 时为组件设置唯一的 key,以便 Vue 能够正确识别组件的状态。
<component v-if="isVisible" :key="componentKey" />

3. v-ifv-show 的选择问题

  • 问题描述: v-if 会完全销毁和重新创建组件,而 v-show 只是切换 display 样式。在某些场景下,频繁使用 v-if 可能会导致性能问题。
  • 解决方案: 如果需要频繁切换显示/隐藏状态,考虑使用 v-show 代替 v-if
<div v-show="isVisible">
  Content
</div>

4. 抖音小程序的渲染机制问题

  • 问题描述: 抖音小程序的渲染机制可能与 Vue3v-if 不完全兼容,导致某些情况下 v-if 的切换未能正确触发视图更新。
  • 解决方案: 尝试使用 wx:if(微信小程序原生指令)代替 v-if,或者在 v-if 切换时手动触发视图更新。
<div wx:if="isVisible">
  Content
</div>

5. v-if 与异步数据的处理问题

  • 问题描述: 在异步数据加载完成后使用 v-if 切换显示内容时,可能会导致视图未及时更新。
  • 解决方案: 确保在异步数据加载完成后,手动触发视图更新,或者使用 watch 监听数据变化。
<script>
export default {
  data() {
    return {
      isVisible: false,
      dataLoaded: false
    };
  },
  watch: {
    dataLoaded(newVal) {
      if (newVal) {
        this.isVisible = true;
      }
    }
  },
  async created() {
    await this.loadData();
    this.dataLoaded = true;
  },
  methods: {
    async loadData() {
      // 异步加载数据
    }
  }
};
</script>
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!