插件
Nuxt 拥有一个插件系统,用于在创建 Vue 应用程序时使用 Vue 插件等。
Nuxt 自动读取 plugins/
目录中的文件,并在创建 Vue 应用程序时加载它们。
内部的所有插件都会自动注册,您无需单独将其添加到
nuxt.config
中。您可以在文件名中使用
.server
或 .client
后缀,以便仅在服务器端或客户端加载插件。已注册的插件
只有目录顶层的文件(或任何子目录中的索引文件)才会被自动注册为插件。
目录结构
-| plugins/
---| foo.ts // scanned
---| bar/
-----| baz.ts // not scanned
-----| foz.vue // not scanned
-----| index.ts // currently scanned but deprecated
只有 foo.ts
和 bar/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 => {
// Doing something with nuxtApp
})
对象语法插件
也可以使用对象语法定义插件,以满足更高级的用例。例如
plugins/hello.ts
export default defineNuxtPlugin({
name: 'my-plugin',
enforce: 'pre', // or 'post'
async setup (nuxtApp) {
// this is the equivalent of a normal functional plugin
},
hooks: {
// You can directly register Nuxt app runtime hooks here
'app:created'() {
const nuxtApp = useNuxtApp()
// do something in the hook
}
},
env: {
// Set this value to `false` if you don't want the plugin to run when rendering server-only or island components.
islands: true
}
})
如果您使用对象语法,则会静态分析属性以生成更优化的构建。因此,您不应该在运行时定义它们。
例如,设置
例如,设置
enforce: import.meta.server ? 'pre' : 'post'
将会破坏 Nuxt 能够对您的插件进行的任何未来优化。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) {
// the next plugin will be executed immediately
}
})
具有依赖项的插件
如果某个插件需要在运行之前等待另一个插件,您可以将该插件的名称添加到 dependsOn
数组中。
plugins/depending-on-my-plugin.ts
export default defineNuxtPlugin({
name: 'depends-on-my-plugin',
dependsOn: ['my-plugin'],
async setup (nuxtApp) {
// this plugin will wait for the end of `my-plugin`'s execution before it runs
}
})
使用组合式函数
plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
const foo = useFoo()
})
但是,请记住有一些限制和差异
如果组合式函数依赖于稍后注册的另一个插件,则它可能无法正常工作。
插件按顺序依次调用,并且在其他所有内容之前调用。您可能使用了依赖于另一个尚未调用的插件的组合式函数。
插件按顺序依次调用,并且在其他所有内容之前调用。您可能使用了依赖于另一个尚未调用的插件的组合式函数。
如果组合式函数依赖于 Vue.js 生命周期,则它将无法正常工作。
通常,Vue.js 组合式函数绑定到当前组件实例,而插件仅绑定到
通常,Vue.js 组合式函数绑定到当前组件实例,而插件仅绑定到
nuxtApp
实例。提供辅助函数
如果您想在 NuxtApp
实例上提供辅助函数,请在 provide
键下从插件返回它。
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`
}
}
})
然后您可以在组件中使用该辅助函数
components/Hello.vue
<script setup lang="ts">
// alternatively, you can also use it here
const { $hello } = useNuxtApp()
</script>
<template>
<div>
{{ $hello('world') }}
</div>
</template>
请注意,我们强烈建议使用
组合式函数
而不是提供辅助函数,以避免污染全局命名空间并保持主包入口文件较小。如果您的插件提供了
这是由于 Vue 如何处理不是模板顶层的 ref 的方式。您可以在 Vue 文档 中阅读更多相关内容。
ref
或 computed
,则它不会在组件 <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 Analytics 标记,您可以使用 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
中为服务器提供一个“存根”指令。