uni-app Vite+Vue3抖音小程序组件使用v-if引发的BUG
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元素
感谢反馈,已复现该问题
暂时直接在父组件那里直接使用v-if解决
<PopupNew v-if="showPopup">
<template>
<view>Ni Hao</view>
</template>
</PopupNew>
感谢跟踪, 期待修复!
进一步排查,发现是抖音小程序官方那边的问题,用原生抖音小程序语言在自定义组件里面使用的tt:if时,组件不会自动销毁,需要去抖音小程序官方社区进行反馈
在使用 uni-app
+ Vite
+ Vue3
开发抖音小程序时,使用 v-if
可能会引发一些 BUG。以下是一些可能的原因和解决方案:
1. v-if
与 v-for
的优先级问题
- 问题描述: 在
Vue3
中,v-if
的优先级高于v-for
,而在Vue2
中则相反。如果你在同一个元素上同时使用v-if
和v-for
,可能会导致渲染错误。 - 解决方案: 避免在同一个元素上同时使用
v-if
和v-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-if
与 key
的配合问题
- 问题描述: 在使用
v-if
时,如果组件的key
没有正确设置,可能会导致组件状态未正确重置或复用。 - 解决方案: 确保在使用
v-if
时为组件设置唯一的key
,以便 Vue 能够正确识别组件的状态。
<component v-if="isVisible" :key="componentKey" />
3. v-if
与 v-show
的选择问题
- 问题描述:
v-if
会完全销毁和重新创建组件,而v-show
只是切换display
样式。在某些场景下,频繁使用v-if
可能会导致性能问题。 - 解决方案: 如果需要频繁切换显示/隐藏状态,考虑使用
v-show
代替v-if
。
<div v-show="isVisible">
Content
</div>
4. 抖音小程序的渲染机制问题
- 问题描述: 抖音小程序的渲染机制可能与
Vue3
的v-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>