实际前端开发中,常用指令的封装
- 全局指令处理步骤
- main.ts
- 指令目录结构
- src/directives/index.ts
- 一、输入框空格禁止指令
- 1、指令文件clearSpace.ts
- 2、指令使用
全局指令处理步骤
main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { setupGlobDirectives } from "@/directives";const app = createApp(App);
// 注册全局指令
setupGlobDirectives(app);
app.mount("#app");
指令目录结构
src/directives/index.ts
import type { App } from "vue";
import { setupNoSpaceDirective } from "./clearSpace";export function setupGlobDirectives(app: App) {setupNoSpaceDirective(app);
}
一、输入框空格禁止指令
1、禁止输入空格; 2、粘贴空格文本时,自动取消所有空格
1、指令文件clearSpace.ts
import type { App } from "vue";// v-no-space: 自定义指令处理输入框的空格,如 SJFW0012 025062 301000 00007
// 通过自定义指令在去掉空格的同时,也实现了响应式function insertTextAtCursor(inputElement: any, text: any) {// 获取当前光标位置const start = inputElement.selectionStart;const end = inputElement.selectionEnd;// 获取输入框的当前值const value = inputElement.value;// 在光标位置插入文本const newValue = value.substring(0, start) + text + value.substring(end);// 更新输入框的值inputElement.value = newValue;// 计算新的光标位置const newCursorPos = start + text.length;// 设置新的光标位置inputElement.setSelectionRange(newCursorPos, newCursorPos);// 触发 input 事件,以便 Vue 等框架可以捕获到变化const event = new Event("input", { bubbles: true, cancelable: true });inputElement.dispatchEvent(event);
}const noSpaceDirective = {mounted(el: any) {const input = el.tagName === "INPUT" ? el : el.querySelector("input");if (input) {// 处理输入事件const handleInput = () => {const start = input.selectionStart;const value = input.value;const newValue = value.replace(/\s/g, "");// 更新输入框的值if (value !== newValue) {input.value = newValue;// 触发v-model更新el.dispatchEvent(new Event("input"));// 恢复光标位置const diff = value.length - newValue.length;setTimeout(() => {input.setSelectionRange(start - diff, start - diff);}, 0);}};// 处理粘贴事件const handlePaste = (e: any) => {e.preventDefault();// const text = (e.clipboardData || (window as any).clipboardData).getData("text");// const cleanedText = text.replace(/\s/g, "");// // 插入清理后的文本,b被弃用了// document.execCommand("insertText", false, cleanedText);// 获取剪贴板内容const clipboardData = e.clipboardData || (window as any).clipboardData;const pastedText = clipboardData.getData("text");// 清理文本(去掉空格)const cleanedText = pastedText.replace(/\s/g, "");// 将清理后的文本插入到当前光标位置insertTextAtCursor(e.target, cleanedText);};// 阻止空格键输入const handleKeydown = (e: any) => {if (e.key === " " || e.key === "Spacebar" || e.keyCode === 32) {e.preventDefault();}};input.addEventListener("input", handleInput);input.addEventListener("paste", handlePaste);input.addEventListener("keydown", handleKeydown);// 存储事件处理函数以便卸载el.__noSpaceHandlers = { handleInput, handlePaste, handleKeydown };}},beforeUnmount(el: any) {if (el.__noSpaceHandlers) {const { handleInput, handlePaste, handleKeydown } = el.__noSpaceHandlers;const input = el.tagName === "INPUT" ? el : el.querySelector("input");if (input) {input.removeEventListener("input", handleInput);input.removeEventListener("paste", handlePaste);input.removeEventListener("keydown", handleKeydown);}delete el.__noSpaceHandlers;}},
};// 自定义 v-no-space 指令
export function setupNoSpaceDirective(app: App) {app.directive("no-space", noSpaceDirective);
}export default noSpaceDirective;