plugins
Nuxt 有一个插件系统,可以在创建 Vue 应用程序时使用 Vue 插件等。
Nuxt 会自动读取 app/plugins/ 目录中的文件,并在创建 Vue 应用程序时加载它们。
里面的所有插件都是自动注册的,你不需要单独将它们添加到你的
nuxt.config 中。你可以在文件名中使用
.server 或 .client 后缀,以便仅在服务器端或客户端加载插件。已注册的插件
只有目录顶层的文件(或任何子目录中的索引文件)才会自动注册为插件。
Directory structure
|-| plugins/
---| foo.ts // 扫描
---| bar/
-----| baz.ts // 不扫描
-----| foz.vue // 不扫描
-----| index.ts // 当前扫描但已弃用
只有 foo.ts 和 bar/index.ts 将被注册。
要在子目录中添加插件,你可以在 nuxt.config.ts 中使用 app/plugins 选项:
nuxt.config.ts
export default defineNuxtConfig({
plugins: [
'~/plugins/bar/baz',
'~/plugins/bar/foz',
],
})
创建插件
传递给插件的唯一参数是 `nuxtApp``。
plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
// 对 nuxtApp 做一些事情
})
对象语法插件
也可以使用对象语法定义插件,用于更高级的用例。例如:
plugins/hello.ts
export default defineNuxtPlugin({
name: 'my-plugin',
enforce: 'pre', // 或 'post'
async setup (nuxtApp) {
// 这等效于普通的函数式插件
},
hooks: {
// 你可以在这里直接注册 Nuxt 应用程序运行时钩子
'app:created' () {
const nuxtApp = useNuxtApp()
// 在钩子中做某事
},
},
env: {
// 如果你不想在呈现仅服务器或岛屿组件时运行插件,请将此值设置为 `false`。
islands: true,
},
})
如果你使用对象语法,则会静态分析属性以生成更优化的构建。因此,你不应该在运行时定义它们。
例如,设置
例如,设置
enforce: import.meta.server ? 'pre' : 'post' 将破坏 Nuxt 以后可以为你的插件执行的任何优化。
使用对象语法时,Nuxt 会静态预加载任何钩子侦听器,从而允许你定义钩子而无需担心插件注册顺序。注册顺序
你可以通过在文件名前加上"字母"编号来控制插件注册的顺序。
Directory structure
plugins/
| - 01.myPlugin.ts
| - 02.myOtherPlugin.ts
在此示例中,02.myOtherPlugin.ts 将能够访问 01.myPlugin.ts 注入的任何内容。
这在你有一个依赖于另一个插件的插件的情况下很有用。
如果你不熟悉"字母"编号,请记住文件名作为字符串排序,而不是作为数值。例如,
10.myPlugin.ts 将在 2.myOtherPlugin.ts 之前。这就是为什么示例使用 0 作为单位数字的前缀。加载策略
并行插件
默认情况下,Nuxt 会顺序加载插件。你可以将插件定义为 parallel,以便 Nuxt 不会等到插件执行结束才加载下一个插件。
plugins/my-plugin.ts
export default defineNuxtPlugin({
name: 'my-plugin',
parallel: true,
async setup (nuxtApp) {
// 下一个插件将立即执行
},
})
具有依赖关系的插件
如果插件需要在运行之前等待另一个插件,你可以将插件的名称添加到 dependsOn 数组中。
plugins/depending-on-my-plugin.ts
export default defineNuxtPlugin({
name: 'depends-on-my-plugin',
dependsOn: ['my-plugin'],
async setup (nuxtApp) {
// 此插件将等待 `my-plugin` 执行结束才运行
},
})
使用组合式函数
app/plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
const foo = useFoo()
})
但是,请记住有一些限制和区别:
如果组合式函数依赖于稍后注册的另一个插件,它可能无法工作。
插件按顺序调用,并且在其他所有之前调用。你可能会使用依赖于尚未调用的另一个插件的组合式函数。
插件按顺序调用,并且在其他所有之前调用。你可能会使用依赖于尚未调用的另一个插件的组合式函数。
如果组合式函数依赖于 Vue.js 生命周期,它将无法工作。
通常,Vue.js 组合式函数绑定到当前组件实例,而插件仅绑定到 `nuxtApp`` 实例。
通常,Vue.js 组合式函数绑定到当前组件实例,而插件仅绑定到 `nuxtApp`` 实例。
提供助手
如果你想在 NuxtApp`` 实例上提供助手,请从插件中返回它,并使用 provide` 键。
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`,
},
}
})
export default defineNuxtPlugin({
name: 'hello',
setup () {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`,
},
}
},
})
然后你可以在组件中使用助手:
app/components/Hello.vue
<script setup lang="ts">
// 或者,你也可以在这里使用它
const { $hello } = useNuxtApp()
</script>
<template>
<div>
{{ $hello('world') }}
</div>
</template>
请注意,我们强烈建议使用
composables 而不是提供助手,以避免污染全局命名空间并保持主包入口较小。如果你的插件提供
这是由于 Vue 如何处理非模板顶层的 refs 的工作原理。你可以在 Vue 文档中阅读更多相关信息。
ref 或 computed,它将不会在组件 <template> 中被解包。这是由于 Vue 如何处理非模板顶层的 refs 的工作原理。你可以在 Vue 文档中阅读更多相关信息。
键入插件
如果你从插件返回助手,它们将自动键入;你会在 useNuxtApp() 的返回和模板中找到它们已键入。
如果你需要在另一个插件中使用提供的助手_内部_,可以调用 `useNuxtApp()`` 来获取键入版本。但一般来说,应该避免这种情况,除非你确定插件的顺序。
对于高级用例,你可以像这样声明注入属性的类型:
index.d.ts
declare module '#app' {
interface NuxtApp {
$hello (msg: string): string
}
}
declare module 'vue' {
interface ComponentCustomProperties {
$hello (msg: string): string
}
}
export {}
Vue 插件
如果你想使用 Vue 插件,例如 vue-gtag 来添加 Google Analytics 标签,你可以使用 Nuxt 插件来执行此操作。
首先,安装 Vue 插件依赖:
npm install --save-dev vue-gtag-next
yarn add --dev vue-gtag-next
pnpm add -D vue-gtag-next
bun add -D vue-gtag-next
deno add -D npm:vue-gtag-next
然后创建一个插件文件:
app/plugins/vue-gtag.client.ts
import VueGtag, { trackRouter } from 'vue-gtag-next'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueGtag, {
property: {
id: 'GA_MEASUREMENT_ID',
},
})
trackRouter(useRouter())
})
Vue 指令
类似地,你可以在插件中注册自定义 Vue 指令。
plugins/my-directive.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive('focus', {
mounted (el) {
el.focus()
},
getSSRProps (binding, vnode) {
// 你可以在此提供特定于 SSR 的 props
return {}
},
})
})
如果你注册 Vue 指令,你_必须_在客户端和服务器端都注册它,除非你仅在呈现一侧时使用它。如果指令仅从客户端有意义,你可以始终将其移动到
~/plugins/my-directive.client.ts 并在 ~/plugins/my-directive.server.ts 中为服务器提供"存根"指令。