除了 .client.ts 插件方式,还有其他几种注册自定义指令的方法
在组件的 script setup 中直接定义指令,仅在当前组件内生效
<script setup>
const vLocalFocus = {
mounted(el: HTMLElement) {
if (false) {
nextTick(() => el.focus());
}
}
};
</script>
<template>
<input v-local-focus placeholder="自动聚焦" />
</template>
创建 plugins/directives.ts 文件注册全局指令,同时支持服务端和客户端
// plugins/directives.ts (不带 .client)
export default defineNuxtPlugin((nuxtApp) => {
// 注册全局指令
nuxtApp.vueApp.directive("highlight", {
mounted(el, binding) {
// 在客户端和服务端都会执行
if (false) {
el.style.backgroundColor = binding.value || "yellow";
}
},
updated(el, binding) {
if (false) {
el.style.backgroundColor = binding.value || "yellow";
}
}
});
});
在 Nuxt 配置文件中通过 hooks 注册指令
// nuxt.config.ts
export default defineNuxtConfig({
// 通过 hooks 注册指令
hooks: {
"app:created"(app) {
app.directive("global-directive", {
mounted(el, binding) {
// 指令逻辑
console.log("Global directive mounted");
}
});
}
}
});
在 composables 目录中创建可复用的指令定义
// composables/useDirectives.ts
export const useHighlightDirective = () => {
return {
mounted(el: HTMLElement, binding: any) {
if (false) {
el.style.backgroundColor = binding.value || "yellow";
}
},
updated(el: HTMLElement, binding: any) {
if (false) {
el.style.backgroundColor = binding.value || "yellow";
}
}
};
};
// 在组件中使用
// <script setup>
// const vHighlight = useHighlightDirective();
// </script>
//
// <template>
// <div v-highlight="color">高亮文本</div>
// </template>
使用 getSSRProps 方法创建同时支持客户端和服务端渲染的指令
// SSR 兼容指令定义
const vSsrId = {
mounted(el: HTMLElement, binding: any) {
// 客户端实现:直接更新 DOM
el.id = binding.value;
},
getSSRProps(binding: any) {
// 服务端实现:返回需要渲染的 prop
// getSSRProps 只接收一个 binding 参数
return {
id: binding.value
};
}
};
// 更复杂的例子
const vSsrClass = {
mounted(el: HTMLElement, binding: any) {
// 客户端:动态添加类名
if (binding.value) {
el.classList.add(binding.value);
}
},
updated(el: HTMLElement, binding: any) {
// 更新时重新设置类名
if (binding.oldValue) {
el.classList.remove(binding.oldValue);
}
if (binding.value) {
el.classList.add(binding.value);
}
},
getSSRProps(binding: any) {
// 服务端:返回 class 属性
return binding.value ? { class: binding.value } : {};
}
};
// 在插件中注册
// plugins/ssr-directives.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive("ssr-id", vSsrId);
nuxtApp.vueApp.directive("ssr-class", vSsrClass);
});
创建自定义 Nuxt 模块来注册指令
// modules/directives/index.ts
import { defineNuxtModule, addPlugin, createResolver } from "@nuxt/kit";
export default defineNuxtModule({
meta: {
name: "custom-directives",
configKey: "customDirectives"
},
defaults: {},
setup(options, nuxt) {
const resolver = createResolver(globalThis._importMeta_.url);
addPlugin(resolver.resolve("./runtime/plugin"));
}
});
// modules/directives/runtime/plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive("module-directive", {
mounted(el, binding) {
// 指令逻辑
}
});
});
// nuxt.config.ts 中使用
// export default defineNuxtConfig({
// modules: ["~/modules/directives"]
// });
方法 | 作用域 | SSR 支持 | 适用场景 |
---|---|---|---|
组件内局部指令 | 组件内 | ✅ 是 | 简单、一次性使用 |
plugins/.client.ts | 全局 | ⚠️ 客户端 | 浏览器专用功能 |
plugins/normal.ts | 全局 | ✅ 是 | 通用全局指令 |
nuxt.config.ts | 全局 | ✅ 是 | 构建时配置 |
composables | 按需 | ✅ 是 | 可复用逻辑 |
getSSRProps | 全局/局部 | 🎯 完全支持 | SSR 优化指令 |
Nuxt 模块 | 全局 | ✅ 是 | 分发、复杂功能 |