思考🤔:什么是插件?和中间件的区别?
- 中间件: 对数据流做中间处理
- 插件:扩展应用的功能
app.use(router).use(pinia).use(ElementPlus).mount('#app')插件基础知识#
创建插件
Nuxt 推荐将插件放置于 plugins 目录下,例如:
-| plugins/---| foo.ts // 被扫描---| bar/-----| baz.ts // 不被扫描-----| foz.ts // 不被扫描Nuxt会自动读取 plugins 目录中的文件,并在创建 Vue 应用程序时加载它们。这意味着该目录下的所有插件,都是自动注册的,无需单独去 nuxt.config.ts 文件中进行配置。
Nuxt 默认只会扫描一层目录。如果希望扫描多层,需要在 nuxt.config.ts 文件中进行配置。
export default defineNuxtConfig({ plugins: ['~/plugins/bar/baz', '~/plugins/bar/foz'],})每个插件是一个 ts 文件,会导出 defineNuxtPlugin 方法的调用:
export default defineNuxtPlugin()defineNuxtPlugin 接收一个回调函数,该回调函数就是插件的主逻辑,回调函数会自动传入 nuxtApp 参数。
export default defineNuxtPlugin((nuxtApp) => { // 使用nuxtApp做一些操作})可以通过环境变量来指定特定的环境下执行插件逻辑:
export default defineNuxtPlugin((nuxtApp) => { // 指定插件只在客户端执行 if (import.meta.server) return // 插件逻辑})nuxtApp
这是一个运行时上下文对象,提供了许多全局的工具和功能,贯穿于服务端和客户端运行时。官方的文档介绍在 这里。该对象上面有如下的成员:
const nuxtApp = { vueApp, // 全局的Vue实例,有些时候需要拿到Vue实例从而注册Vue的插件或者自定义指令
versions, // Nuxt以及Vue的版本信息
// These let you call and add runtime NuxtApp hooks // https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/nuxt.ts#L18 hooks, hook, callHook,
// 仅在 SSR 期间可用,主要包含一些和服务端相关的上下文信息 ssrContext: { url, req, res, runtimeConfig, noSSR, },
// 服务端向客户端传递的数据载体 payload: { serverRendered: true, // 是否为服务器渲染 data: {}, // 服务端要向客户端返回的数据 state: {} // 客户端的初始状态 }
// 注册全局功能模块 provide: (name: string, value: any) => void}nuxtApp.hook('app:mounted', () => {})该对象具体对应的属性和方法可以参阅这里。
在使用 defineNuxtPlugin 创建插件时,回调函数可以返回一个对象,该对象可以为 nuxtApp 对象提供扩展内容:
export default defineNuxtPlugin(() => { // 为nuxtApp对象提供扩展内容 return { provide: { //... }, }})对象写法
除了回调函数的形式,defineNuxtPlugin 还支持对象写法:
export default defineNuxtPlugin({ name: 'my-plugin', enforce: 'pre', async setup(nuxtApp) {}, hooks: { 'app:created'() { const nuxtApp = useNuxtApp() }, }, env: { islands: true, },})-
name:插件的名称
-
enforce:插件加载的顺序
- pre:你的这个插件在 Nuxt 核心插件加载之前运行
- post:你的这个插件在 Nuxt 核心插件加载之后运行
-
setup:插件的主要逻辑
-
hooks:对应上面的 hooks
-
env:控制插件的运行环境
- islands:插件是否在岛屿组件中运行
加载插件
Nuxt 应用在加载插件的时候,和加载中间件一样,按照 ASCII 码顺序进行加载。如果希望改变加载的顺序,在插件文件前面添加序号即可:
plugins/ | - 01.myPlugin.ts | - 02.myOtherPlugin.ts加载插件时默认是按照顺序进行加载,将 parallel 设置为 true 可设置为并行加载,Nuxt 不会等到该插件执行结束,而是会直接加载下一个插件。
export default defineNuxtPlugin({ name: 'my-plugin', parallel: true, // 加载这个插件的时候,是并行加载,不用等到该插件加载结束,直接开始加载下一个插件 async setup(nuxtApp) { // 下一个插件将立即执行 },})使用组合式API以及工具函数
在插件中,可以使用内置的或者自定义的组合式 API 以及工具函数。例如:
export const useFoo = () => { return useState('foo', () => 'bar')}export default defineNuxtPlugin((nuxtApp) => { const foo = useFoo() console.log(foo.value)})启动应用后,会自动执行该插件代码。
注册Vue插件#
Vue也是支持插件的。如果想要使用 Vue 插件,可以使用 Nuxt 插件来间接的进行注册。先获取到 Vue 的实例
例如,在Vue项目里面,使用 vue-gtag 这个插件来添加 Google Analytics 标签:
import { createApp } from 'vue'import App from './App.vue'// 引入import VueGtag from 'vue-gtag'const app = createApp(App)// 注册app .use(VueGtag, { config: { id: 'GA_MEASUREMENT_ID' }, }) .mount('#app')如果想要在 Nuxt 项目中使用该插件:
import VueGtag, { trackRouter } from 'vue-gtag-next'
export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(VueGtag, { property: { id: 'GA_MEASUREMENT_ID', }, }) trackRouter(useRouter())})课堂练习
实现一个全局事件总线插件,在不引入状态管理工具(pinia or vuex)的情况下进行组件通信。
-EOF-