我正在使用 Nuxt 3 构建一个应用程序,我想添加一个页面加载器直到网站加载。
根据这篇文章。有一种简单但有限的解决方案和一种完全定制的解决方案。
<NuxtLoadingIndicator>
<NuxtLoadingIndicator>
包含一个加载进度条,可以像这样使用
<template>
<NuxtLayout>
<NuxtLoadingIndicator />
<NuxtPage />
<NuxtLayout>
</template>
但它只有一个预定义的 UI,并且只能使用这几个属性进行自定义
如果您需要自定义加载程序(例如带背景的全屏旋转器),则需要不同的方法。这种方法允许您创建任何加载程序并在需要时显示它。
<template>
<div class="h-screen">
<div v-if="loading" class="fixed left-0 top-0 h-0.5 w-full z-50 bg-green-500" />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
const nuxtApp = useNuxtApp();
const loading = ref(false);
nuxtApp.hook("page:start", () => {
loading.value = true;
});
nuxtApp.hook("page:finish", () => {
loading.value = false;
});
</script>
Nuxt3 提供了应用程序运行时挂钩,其中包含针对
page:start
和 page:finish
事件的拦截器。要正确使用它们,您需要以这种方式使用这些钩子(在 app.vue 或您的自定义组件中):
“
<NuxtLoadingIndicator>
组件在页面导航上显示进度条。” – 来自 Nuxt3 文档 <NuxtLoadingIndicator>
。
我认为这也是用于在开发设置中显示加载指示器的。
我为 Nuxt3 制作了一个自定义解决方案,使用 pinia 进行状态管理和全局中间件,该解决方案的工作原理与 Nextjs-ProgressBar
商店/ui.js
import { defineStore } from "pinia";
const useUiStore = defineStore("uiStore", {
state: () => {
return {
pageLoader: false,
};
},
actions: {
setPageLoader(value) {
this.pageLoader = value
},
},
});
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useUiStore, import.meta.hot));
}
export default useUiStore;
中间件/ui.global.js
import useUiStore from "~~/stores/ui";
export default defineNuxtRouteMiddleware(async(to, from) => {
useUiStore().setPageLoader(true)
})
组件/LoaderIndicator.vue
<script setup>
import useUiStore from '~~/stores/ui';
const nuxtApp = useNuxtApp();
nuxtApp.hook("page:finish", () => {
if(useUiStore().$state.pageLoader == true){
useUiStore().setPageLoader(false)
}
});
</script>
<script>
export default {
watch: {
showLoader(newVal, oldVal) {
if (newVal == true) {
this.$refs.progressBar.style.opacity = '1';
this.$refs.progressBar.style.transitionDuration = '1000ms';
this.$refs.progressBar.style.width = '40%';
} else if (newVal == false) {
this.$refs.progressBar.style.transitionDuration = '1000ms';
this.$refs.progressBar.style.width = '100%';
setTimeout(() => {
this.$refs.progressBar.style.opacity = '0';
this.$refs.progressBar.style.transitionDuration = '0ms';
this.$refs.progressBar.style.width = '0%';
}, 1000);
}
},
},
computed: {
showLoader() {
return useUiStore().$state.pageLoader;
}
},
};
</script>
<template>
<div ref="progressBar" class="fixed left-0 top-0 z-50 transition-all bg-orange h-[3px] LoadingBar shadow-[0_0_10px] shadow-orange " :style="{ width :'0%' }"></div>
</template>
应用程序.vue
<template>
<NuxtLayout>
<LoaderIndicator />
<NuxtPage />
</NuxtLayout>
</template>
请评论优化
谢谢你
我没有使用
<NuxtLoadingIndicator>
,而是使用了全局中间件 + page:finish
钩子,例如:
<template>
<div v-show="show">
Loading...
</div>
</template>
<script setup>
const nuxtApp = useNuxtApp();
const show = ref(false);
addRouteMiddleware('global-loader', () => {
show.value = true
}, {
global: true
})
nuxtApp.hook('page:finish', () => { show.value = false; })
</script>
因此,在每次路线更改时,我们都会显示加载程序并在显示页面时隐藏它。
您可以将模板替换为您想要的模板,一些旋转器或其他东西。
我认为这也有帮助,但它涉及 javascript。
<div id="loading">Loading...</div>
~/plugins/loading.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('page:finish', () => {
const loadingElement = document.querySelector('#loading')
if (loadingElement) {
loadingElement.remove()
}
})
})
一旦钩子触发,它将删除文档中的微调器。