Nuxt 插件
Nuxt 插件是一种机制,允许你在 Vue 应用初始化前后注入自定义功能。它们可以用于:
注意
注册全局组件
添加 Vue 插件
定义全局混入(mixins)
创建自定义指令
提供全局工具函数
集成第三方库
插件系统是 Nuxt 架构的核心部分,许多官方模块(如 Pinia、Auth、i18n)都是通过插件方式集成到 Nuxt 应用中的。
插件基础
创建你的第一个插件
在 Nuxt 项目中,插件存放在 plugins 目录中。创建一个新插件只需几个简单步骤:
在项目根目录下创建 plugins 文件夹(如果不存在)
在 plugins 目录中创建新的 JavaScript 文件,例如 my-first-plugin.js
一个最基本的插件结构如下
// plugins/my-first-plugin.js
export default defineNuxtPlugin((nuxtApp) => {
// 这里可以访问 nuxtApp 实例
console.log("我的第一个Nuxt插件已加载!");
// 可以返回一个对象,提供全局可用的功能
return {
provide: {
sayHello: (name) => `你好, ${name}!`,
},
};
});
注册到 Nuxt 应用
- nuxt.config.js
注意
在 plugins 目录中要是没有二级目录 nuxt3 会自动识别,不用注册
要是有二级目录 请看我下面的代码
- 注册插件
// 安装插件
plugins: [
'~/plugins/rem/flexible.js',
'~/plugins/elementicon/element-plus-icons.js',
'~/plugins/myCustom/myCustom.js',
'~/plugins/myCustom/myCustom.client.js',
'~/plugins/myCustom/myCustom.server.js',
'~/plugins/myCustom/myError.js',
'~/plugins/myCustom/myzhiling.js'
],
使用
<div class="textColor">登录页面内容--{{ $sayHelloCustom('李四') }}</div>
插件类型与执行环境
客户端 vs 服务端插件
默认情况下,插件会在客户端和服务端
都运行。但在某些情况下,你可能需要指定插件只在特定环境中运行:
仅客户端插件
:添加.client
后缀,如 my-plugin.client.js仅服务端插件
:添加.server
后缀,如 my-plugin.server.js
// plugins/analytics.client.js - 只在客户端运行
export default defineNuxtPlugin((nuxtApp) => {
// 初始化客户端分析工具
console.log("初始化分析工具 (仅客户端)");
});
插件执行顺序
插件执行顺序有时很重要,特别是当插件之间存在依赖关系时。Nuxt 提供了几种控制顺序的方法:
注意
文件名前缀 使用数字前缀加载顺序.比如
01-plugin.js
比02-plugin.js
执行顺序靠前目录结构:插件按照字母顺序加载,数字前缀拥有更高优先级
显示顺序: 在 nuxt.config.js 中 plugins 数组中数组顺序
// nuxt.config.js
export default defineNuxtConfig({
plugins: ["~/plugins/01-first-plugin.js", "~/plugins/02-second-plugin.js"],
});
插件的高级用法
集成 Vue 插件
许多 Vue 插件可以轻松集成到 nuxt
// plugins/vue-toastification.js
import Toast from "vue-toastification";
import "vue-toastification/dist/index.css";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toast, {
timeout: 2000,
position: "top-right",
});
});
注册全局组件
对于在整个应用中频繁使用的组件,全局注册可以简化导入
// plugins/global-components.js
import MyButton from "~/components/ui/MyButton.vue";
import MyInput from "~/components/ui/MyInput.vue";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("MyButton", MyButton);
nuxtApp.vueApp.component("MyInput", MyInput);
});
创建自定义指令
自定义指令是 Vue 的强大功能,可以通过插件全局注册:
// plugins/directives.js
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive("focus", {
mounted(el) {
el.focus();
},
updated(el) {
el.focus();
},
});
nuxtApp.vueApp.directive("animate", {
mounted(el, binding) {
el.style.transition = "all 0.3s";
el.addEventListener("mouseenter", () => {
el.style.transform = "scale(1.05)";
});
el.addEventListener("mouseleave", () => {
el.style.transform = "scale(1)";
});
},
});
});
- 使用自定义指令
<input type="text":value="valueinput" v-focus ></input>
提供全局的工具函数
通过插件的 provide 选项,可以创建全局可用的工具函数:
// plugins/utilities.js
export default defineNuxtPlugin((nuxtApp) => {
const utilities = {
formatDate(date, locale = "en-US") {
return new Date(date).toLocaleDateString(locale);
},
truncate(text, length = 100) {
return text.length > length ? text.substring(0, length) + "..." : text;
},
copyToClipboard(text) {
// 判断是否服务器还是客户端
if (process.client) {
navigator.clipboard.writeText(text);
}
},
};
return {
provide: {
utils: utilities,
},
};
});
使用这些工具函数
<script setup>
const { $utils } = useNuxtApp();
const formattedDate = $utils.formatDate(new Date());
const truncatedText = $utils.truncate("这是一段很长的文本...", 10);
</script>
异步插件
有时你的插件需要执行异步操作,如获取数据或等待某些资源加载。Nuxt 插件完全支持异步操作:
// plugins/async-plugin.js
export default defineNuxtPlugin(async (nuxtApp) => {
// 模拟异步数据获取
const response = await $fetch("/api/site-settings");
// 将获取的数据提供给整个应用
return {
provide: {
siteSettings: response.data,
},
};
});
插件最佳实践
保持插件轻量
插件在应用启动时运行,应避免执行大量同步操作或复杂的计算,这会拖慢应用启动速度。
合理组织插件
按功能划分插件(如 axios.js、auth.js、ui-components.js)
为插件添加清晰的命名和注释
考虑将大型插件拆分为多个小插件
处理错误
为插件添加适当的错误处理:
// plugins/error-handling.js
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.config.errorHandler = (err, vm, info) => {
// 处理错误
console.error("全局错误:", err);
// 可以发送错误到错误跟踪服务
if (process.client) {
sendToErrorTrackingService(err);
}
};
});
类型安全(TS)
如果你使用 TypeScript,可以为插件提供类型定义:
// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
hello: (name: string): string => `Hello ${name}`,
},
};
});
// types/nuxt.d.ts
declare module "#app" {
interface NuxtApp {
$hello: (name: string) => string;
}
}
实际案例
案例 1 集成 axios
// plugins/axios.js
export default defineNuxtPlugin((nuxtApp) => {
const axios = {
get: (url) => $fetch(url),
post: (url, data) => $fetch(url, { method: "POST", body: data }),
put: (url, data) => $fetch(url, { method: "PUT", body: data }),
delete: (url) => $fetch(url, { method: "DELETE" }),
};
return {
provide: {
axios,
},
};
});
案例 2: 实现权限检查
// plugins/auth.js
export default defineNuxtPlugin((nuxtApp) => {
const auth = {
user: null,
async login(credentials) {
const { data } = await $fetch("/api/login", {
method: "POST",
body: credentials,
});
this.user = data.user;
return data;
},
logout() {
this.user = null;
},
can(permission) {
return this.user?.permissions?.includes(permission);
},
};
return {
provide: {
auth,
},
};
});