实际前端开发中,常用指令的封装
全局指令处理步骤
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;