plugins

Nuxt 提供了一个插件系统,以便在创建 Vue 应用程序时使用 Vue 插件等。

Nuxt 会自动读取 plugins/ 目录中的文件,并在创建 Vue 应用程序时加载它们。

目录内的所有插件都会自动注册,你无需在 nuxt.config 中单独添加它们。
你可以在文件名中使用 .server.client 后缀,以仅在服务器端或客户端加载插件。

已注册插件

只有目录顶层的文件(或任何子目录中的索引文件)才会被自动注册为插件。

目录结构
-| plugins/
---| foo.ts        // 将被扫描
---| bar/
-----| baz.ts      // 不会被扫描
-----| foz.vue     // 不会被扫描
-----| index.ts    // 当前被扫描但已废弃

只有 foo.tsbar/index.ts 会被注册。

要在子目录中添加插件,你可以在 nuxt.config.ts 中使用 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
} })
观看 Alexander Lichter 关于 Nuxt 插件的对象语法视频。
如果你使用对象语法,属性会被静态分析以产生更优化的构建。因此,你不应该在运行时定义它们。:br 例如,设置 enforce: import.meta.server ? 'pre' : 'post' 将会抵消 Nuxt 未来对你的插件所做的任何优化。:br Nuxt 在使用对象语法时会静态预加载所有的钩子监听器,允许你定义钩子而不需要担心插件注册的顺序。

注册顺序

你可以通过在文件名前加上“字母顺序”编号来控制插件的注册顺序。

目录结构
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` 执行完毕后才运行 } })

使用组合式函数

你可以在 Nuxt 插件中使用 组合式函数 以及 实用工具

plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
  const foo = useFoo()
})

但是,请注意存在一些限制和差异:

如果组合式函数依赖于之后注册的另一个插件,则可能无法工作。
插件按顺序依次调用,在所有其他内容之前。你可能使用了一个依赖于尚未调用的另一个插件的组合式函数。
如果组合式函数依赖于 Vue.js 生命周期,则它将不起作用。
通常,Vue.js 组合式函数绑定到当前组件实例,而插件只绑定到 nuxtApp 实例。

提供辅助函数

如果你想在 NuxtApp 实例上提供一个辅助函数,可以在插件中返回它并在 provide 键下。

export default 
defineNuxtPlugin
(() => {
return {
provide
: {
hello
: (
msg
: string) => `Hello ${
msg
}!`
} } })

然后你可以在组件中使用这个辅助函数:

components/Hello.vue
<script setup lang="ts">
// 你也可以在这里使用它
const { $hello } = useNuxtApp()
</script>

<template>
  <div>
    {{ $hello('world') }}
  </div>
</template>
请注意,我们强烈建议使用 组合式函数 而不是提供辅助函数,以避免污染全局命名空间并保持主捆绑包条目小巧。
如果你的插件提供了 refcomputed,它们在组件的 <template> 中不会被展开。
这是由于 Vue 在模板中对非顶级的 ref 处理方式的原因。你可以在 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 {}
如果你使用的是 WebStorm,可能需要增强 @vue/runtime-core,直到 这个问题 得到解决。

Vue 插件

如果你想使用 Vue 插件,比如 vue-gtag 来添加 Google 分析标签,你可以使用一个 Nuxt 插件来实现。

首先,安装 Vue 插件依赖项:

npm install --save-dev vue-gtag-next

然后创建一个插件文件:

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
) {
// you can provide SSR-specific props here return {} } }) })
如果您注册了一个 Vue 指令,除非在渲染时只使用它,否则必须同时在客户端和服务器端进行注册。如果该指令只从客户端方面有意义,则可以将其移动到 ~/plugins/my-directive.client.ts 中,并在 ~/plugins/my-directive.server.ts 中为服务器提供 stub 指令。
Read more in Custom Directives on Vue Docs.