useNuxtApp
useNuxtApp
是一个内置的组合式函数,它让你可以访问以下内容:
Vue 应用程序实例
:你可以通过 useNuxtApp 获取全局的 Vue 应用程序实例,进而使用 Vue 的相关功能,如注册全局组件和指令等。运行时钩子
:你可以使用 hook 方法来注册自定义的钩子,以便在特定的生命周期事件中执行代码。例如,你可以在页面开始渲染时执行某些操作。运行时配置变量:你可以访问 Nuxt 应用的配置变量,这些变量可以在应用的不同部分共享。
内部状态:你可以访问与服务器端渲染(SSR)相关的上下文信息,如 ssrContext 和 payload。这些信息对于处理服务器端请求和响应非常重要。
使用示例
以下是如何在 Nuxt 应用中使用 useNuxtApp 的示例:
在插件中使用
// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
// 提供一个全局函数
nuxtApp.provide("greet", (name) => `Hello, ${name}!`);
// 注册一个钩子
nuxtApp.hook("page:start", () => {
console.log("Page is starting...");
});
});
在组件中使用
<template>
<div>{{ greeting }}</div>
</template>
<script setup>
const nuxtApp = useNuxtApp(); // 获取 nuxtApp 实例
const greeting = nuxtApp.$greet("World"); // 调用提供的函数
</script>
方法
provide
函数是 Nuxt.js 中用于扩展运行时上下文的一个重要功能。通过这个函数,你可以将值和辅助方法提供给 Nuxt 应用中的所有组合函数和组件,使它们能够共享这些值和方法。
provide 函数
provide
函数接受两个参数:
name
:一个字符串,表示你要提供的值的名称。value
:你要提供的值或函数。
使用示例
以下是如何使用 provide
函数创建 Nuxt 插件并在应用中使用它的示例:
- 创建插件
首先,你需要创建一个插件文件,在其中使用 provide 函数:
// plugins/my-plugin.js
export default defineNuxtPlugin((nuxtApp) => {
// 使用 provide 函数提供一个自定义方法
nuxtApp.provide("hello", (name) => `Hello ${name}!`);
});
- 在组件中使用
接下来,你可以在任何组件中使用 useNuxtApp
来访问这个提供的方法:
<template>
<div>{{ greeting }}</div>
</template>
<script setup>
const nuxtApp = useNuxtApp(); // 获取 nuxtApp 实例
// 调用提供的 hello 方法
const greeting = nuxtApp.$hello("World"); // 输出 "Hello World!"
</script>
在上面的示例中,$hello 成为 nuxtApp 上下文的一个新的自定义部分。你可以在任何可以访问 nuxtApp 的地方使用这个方法。
hook 函数
hook
函数用于在 Nuxt 应用的生命周期中注册钩子。它接受两个参数:
name: 一个字符串,表示钩子的名称。
cb:一个回调函数,当钩子被触发时执行。
使用示例
- 创建插件
你可以创建一个插件文件,并在其中使用 hook 函数来注册钩子。例如,下面的代码在页面开始渲染时和 Vue.js 发生错误时添加自定义逻辑:
// plugins/test.ts
export default defineNuxtPlugin((nuxtApp) => {
// 注册一个钩子,在页面开始渲染时触发
nuxtApp.hook("page:start", () => {
console.log("页面开始渲染");
// 在这里添加你的代码,例如记录日志、初始化状态等
});
// 注册一个钩子,当 Vue.js 发生错误时触发
nuxtApp.hook("vue:error", (..._args) => {
console.log("捕获到 Vue 错误:", ..._args);
// 可以在这里进行错误处理,例如发送错误报告
// if (process.client) {
// console.log(..._args);
// }
});
});
- 可用的运行时钩子
Nuxt.js 提供了一些内置的运行时钩子,你可以在应用中使用它们。以下是一些常用的钩子:
page:start
:在页面开始渲染时触发。vue:error
:在 Vue.js 发生错误时触发。app:mounted
:在应用挂载后触发。app:error
:在应用发生错误时触发。
calhook 函数
callHook 函数接受两个参数:
name:一个字符串,表示要调用的钩子的名称。
...args:可选的参数,可以传递给钩子的回调函数。
使用示例
- 创建插件并调用钩子
假设你有一个插件需要在初始化时调用一个名为 my-plugin:init 的钩子,你可以这样实现:
// plugins/myPlugin.ts
export default defineNuxtPlugin((nuxtApp) => {
// 注册一个钩子
nuxtApp.hook("my-plugin:init", () => {
console.log("我的插件初始化钩子被调用");
// 在这里可以执行初始化逻辑
});
// 调用钩子
nuxtApp
.callHook("my-plugin:init")
.then(() => {
console.log("钩子调用完成");
})
.catch((error) => {
console.error("钩子调用出错:", error);
});
});
- 异步调用钩子
由于 callHook 返回一个 Promise,你可以使用 async/await 语法来简化异步调用的处理:
// plugins/myPlugin.ts
export default defineNuxtPlugin(async (nuxtApp) => {
// 注册一个钩子
nuxtApp.hook('my-plugin:init', () => {
console.log('我的插件初始化钩子被调用');
// 在这里可以执行初始化逻辑
});
// 使用 async/await 调用钩子
try {
await nuxtApp.callHook('my-plugin:init');
console.log('钩子调用完成');
} catch (error) {
console.error('钩子调用出错:', error);
}
});
属性
vueApp 属性
vueApp
是全局的 Vue.js 应用程序实例,你可以通过 nuxtApp 访问它。以下是一些有用的方法:
component()
功能: 注册全局组件或检索已注册的组件。
用法
注册组件:
nuxtApp.vueApp.component('MyComponent', MyComponent);
检索组件:
const MyComponent = nuxtApp.vueApp.component('MyComponent');
directive()
功能 注册全局自定义指令或检索已注册的指令。
用法
nuxtApp.vueApp.directive("my-directive", {
// 指令定义
beforeMount(el, binding) {
// 指令逻辑
},
});
- 检索指令
const myDirective = nuxtApp.vueApp.directive("my-directive");
runWithContext
你可能会遇到“Nuxt实例不可用”的消息,所以才会来到这里。请尽量少使用此方法,并报告导致问题的示例,以便最终在框架层面解决。
- 用法
const result = nuxtApp.runWithContext(() => {});
箭头函数里面
:任何需要当前 Nuxt 应用程序上下文的函数。此上下文将自动正确应用。
runWithContext
方法用于调用一个函数并为其提供一个显式的 Nuxt 上下文。通常情况下,Nuxt 上下文会在组件之间隐式传递,无需担心。然而,在中间件/插件中处理复杂的 async/await
场景时,可能会遇到异步调用后当前实例已被取消设置的情况。
export default defineNuxtRouteMiddleware(async (to, from) => {
const nuxtApp = useNuxtApp();
let user;
try {
user = await fetchUser();
// Vue/Nuxt编译器在这里丢失了上下文,因为try/catch块中进行了操作。
} catch (e) {
user = null;
}
if (!user) {
// 将正确的Nuxt上下文应用于我们的`navigateTo`调用。
return nuxtApp.runWithContext(() => navigateTo("/auth"));
}
});