Vue中v-show页面加载内容闪烁问题的解决咨询
这个问题我之前也碰到过,本质原因是浏览器在Vue实例完成挂载前,会先渲染所有未被处理的DOM元素——毕竟浏览器不认识v-show指令,所以那些带有v-show="currentPage == n"的.row div在Vue接管之前,都是默认显示状态,直到Vue编译模板、计算currentPage的值后,才会把不符合条件的div隐藏,这中间的时间差就造成了"闪烁"。
下面给你几个实用的解决办法,按推荐程度排序:
1. 使用Vue官方的v-cloak指令(最推荐)
这是Vue专门为解决初始渲染闪烁问题设计的指令,原理是在Vue实例编译完成前,给元素加上一个v-cloak类,编译完成后自动移除这个类。你只需要两步:
- 第一步:给所有
.row元素(或者直接给Vue的挂载根元素)加上v-cloak属性:<div v-show="currentPage == 1" class="row" v-cloak> ... </div> <div v-show="currentPage == 2" class="row" v-cloak> ... </div> <div v-show="currentPage == 3" class="row" v-cloak> ... </div> - 第二步:在你的CSS中添加样式,隐藏带有
v-cloak类的元素:[v-cloak] { display: none; }
这样,在Vue没准备好之前,所有带v-cloak的元素都会被隐藏,编译完成后自动显示符合v-show条件的内容,完美消除闪烁。
2. 用CSS初始隐藏所有.row元素
如果不想用v-cloak,也可以直接给.row类设置初始隐藏样式,利用Vue内联样式优先级更高的特性覆盖它:
- 在CSS中添加:
.row { display: none; }
Vue的v-show会通过内联样式(比如display: block)覆盖这个类样式,所以当Vue挂载后,符合条件的.row会正常显示,不符合的保持隐藏。初始状态下所有.row都是隐藏的,自然不会闪烁。
3. 改用v-if代替v-show(按需选择)
如果你的页面切换不频繁,也可以把v-show换成v-if:
<div v-if="currentPage == 1" class="row"> ... </div> <div v-if="currentPage == 2" class="row"> ... </div> <div v-if="currentPage == 3" class="row"> ... </div>
v-if是条件渲染,只有当条件为真时,元素才会被渲染到DOM中。Vue挂载后才会渲染符合currentPage的div,其他div根本不会出现在DOM里,所以不会有闪烁问题。但要注意:v-if切换时会销毁/重建组件,性能不如v-show(v-show只是切换CSS的display属性),如果页面切换很频繁,不建议用这个方案。
额外优化:尽早初始化currentPage
因为你的currentPage是从URL hash中获取的,建议在Vue实例的created钩子中尽快读取hash值并设置currentPage,避免初始值为默认值导致的短暂显示:
new Vue({ el: '#app', data() { return { currentPage: 1 // 默认值 } }, created() { // 从URL hash中获取页面编号,比如#2就取2 const hash = window.location.hash.slice(1); if (hash && !isNaN(hash)) { this.currentPage = parseInt(hash); } } })
内容的提问来源于stack exchange,提问作者firsttimeoncomputer

