Nuxt 3页面加载器在图片未加载完成时提前停止的求助
解决Nuxt PWA中等待所有资源(含图片)加载完成再隐藏加载界面的问题
你遇到的问题本质是Nuxt内置的页面钩子和加载指示器只关心页面组件渲染完成,不会等待页面内的图片、字体等静态资源加载完毕。要实现真正的"完全加载"后再显示页面,需要结合浏览器的load事件来判断。
实现思路
- 在页面切换开始时显示加载界面
- 监听浏览器的
load事件,该事件会在页面所有资源(图片、样式、脚本等)加载完成后触发 - 事件触发后隐藏加载界面,同时处理页面切换时的重复监听问题
具体代码实现(在app.vue中)
<template> <div> <!-- 加载遮罩层,覆盖整个屏幕 --> <div v-if="loading" class="fixed inset-0 bg-white z-[9999] flex items-center justify-center"> <div class="w-16 h-16 border-4 border-green-500 border-t-transparent rounded-full animate-spin"></div> </div> <NuxtLayout> <NuxtPage /> </NuxtLayout> </div> </template> <script setup lang="ts"> const loading = ref(true) const nuxtApp = useNuxtApp() // 监听页面切换开始 nuxtApp.hook('page:start', () => { loading.value = true // 每次页面切换时重新绑定事件,避免页面缓存导致事件不触发 window.addEventListener('load', onPageFullLoad, { once: true }) }) // 页面所有资源加载完成的回调 function onPageFullLoad() { loading.value = false } // 初始加载时监听一次 if (process.client) { window.addEventListener('load', onPageFullLoad, { once: true }) } </script> <style scoped> .animate-spin { animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } </style>
关键细节说明
- 使用
{ once: true }确保load事件只触发一次,避免内存泄漏 - 在
page:start钩子中重新绑定事件:SPA页面切换不会刷新浏览器,初始load事件只会触发一次,切换页面需要重新监听 - 加载遮罩层用高
z-index确保覆盖所有内容,防止用户提前操作未加载完成的页面 - 如果你使用Tailwind CSS,直接用框架内置的动画类即可,无需自定义
@keyframes
额外处理:动态加载的图片
如果页面中有接口返回地址后渲染的动态图片,上面的方法可能不适用。这时可以监听每个图片的load事件,统计加载完成的数量,直到所有图片加载完毕再隐藏加载界面:
// 页面组件内示例 const imageUrls = ref(['/img1.jpg', '/img2.jpg']) const loadedCount = ref(0) const loading = ref(true) function handleImageLoad() { loadedCount.value++ if (loadedCount.value === imageUrls.value.length) { loading.value = false } }
模板中给每个动态图片绑定事件:<img v-for="url in imageUrls" :src="url" @load="handleImageLoad">
内容的提问来源于stack exchange,提问作者Driesketeer
相关产品推荐
相关产品推荐

