实际前端开发中,常用指令的封装

发布于:2025-06-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

全局指令处理步骤

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;

2、指令使用

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到