自定义指令 - 去除所有空格和换行

主要功能

  1. 自动去除空格和换行:当用户在输入框中输入内容时,指令会自动去除所有空格和换行符。
  2. 支持不同事件模式 :可以通过指令参数指定监听的事件类型,默认为 input 事件。

代码结构分析

类型声明

typescript 复制代码
declare global {
  interface HTMLInputElement {
    __trimHandler__?: (e: Event) => void
  }
}
  • 扩展了 HTMLInputElement 类型,添加了一个可选属性 __trimHandler__ 用于存储事件处理函数。

指令对象

typescript

javascript 复制代码
const trim: Directive = {
  mounted(el: HTMLInputElement, binding) {
    // 初始化逻辑
  },
  beforeUnmount(el: HTMLInputElement, binding) {
    // 清理逻辑
  },
}

mounted 钩子

  1. 获取模式

    ini 复制代码
    const mode = binding.arg || 'input'
    • 从指令参数获取事件模式,默认使用 input 事件
  2. 创建处理函数

    javascript 复制代码
    const handler = (e: Event) => {
      const value = (e.target as HTMLInputElement).value
      const newValue = value.replace(/\s+/g, '').replace(/\n/g, '')
      
      if (value !== newValue) {
        (e.target as HTMLInputElement).value = newValue
        setTimeout(() => {
          const event = new Event('input', { bubbles: true })
          el.dispatchEvent(event)
        }, 0)
      }
    }
    • 获取输入框当前值
    • 使用正则表达式去除所有空格和换行符
    • 如果值有变化,更新输入框的值
    • 使用 setTimeout 异步触发 input 事件,确保 Vue 能检测到变化
  3. 存储并绑定事件

    ini 复制代码
    el.__trimHandler__ = handler
    el.addEventListener(mode, handler)

beforeUnmount 钩子

markdown 复制代码
if (el.__trimHandler__) {
  el.removeEventListener(mode, el.__trimHandler__)
  delete el.__trimHandler__
}
  • 移除事件监听器
  • 删除存储的处理函数引用

使用示例

xml 复制代码
<template>
  <input v-trim /> <!-- 默认监听 input 事件 -->
  <input v-trim:blur /> <!-- 监听 blur 事件 -->
</template>
js 复制代码
import type { Directive } from 'vue'
declare global {
  interface HTMLInputElement {
    __trimHandler__?: (e: Event) => void
  }
}
const trim: Directive = {
  mounted(el: HTMLInputElement, binding) {
    const mode = binding.arg || 'input'

    const handler = (e: Event) => {
      // 只处理用户真实输入
      const value = (e.target as HTMLInputElement).value
      const newValue = value.replace(/\s+/g, '') // 移除空格与换行

      if (value !== newValue) {
        ;(e.target as HTMLInputElement).value = newValue
        // 注意这里触发 input 事件用 setTimeout,避免同步触发死循环
        setTimeout(() => {
          const event = new Event('input', { bubbles: true })
          el.dispatchEvent(event)
        }, 0)
      }
    }

    el.__trimHandler__ = handler
    el.addEventListener(mode, handler)
  },
  beforeUnmount(el: HTMLInputElement, binding) {
    const mode = binding.arg || 'input'
    if (el.__trimHandler__) {
      el.removeEventListener(mode, el.__trimHandler__)
      delete el.__trimHandler__
    }
  },
}

export default trim
相关推荐
我是若尘1 小时前
用 Git Worktree 同时开多个需求,不用来回 stash
前端
IT_陈寒2 小时前
Vue的v-for为什么不加key也能工作?我差点翻车
前端·人工智能·后端
小碗羊肉2 小时前
【JavaWeb | 第十二篇】项目实战——登录功能
java·前端·数据库
一个处女座的程序猿O(∩_∩)O2 小时前
如何保持nginx配置与前端打包dist的路径保持一致、解决页面刷新白屏以及页面跳转问题
运维·前端·nginx
十有八七2 小时前
AI 开发,本质是一场文档的生命周期管理
前端·人工智能
Hyyy3 小时前
普通前端自救记录——第0周
前端
前端若水3 小时前
在 Vue 2 与 Vue 3 中使用 markdown-it-vue 渲染 Markdown 和数学公式
前端·javascript·vue.js
之歆3 小时前
DAY_10 JavaScript 深度解析:原型链 · 引用类型 · 内置对象 · 数组方法全攻略(下)
开发语言·前端·javascript·ecmascript
行星飞行4 小时前
从 cursor 、 Claude code 迁移到 codex,30 分钟快速上手 codex 常用技巧
前端
Pu_Nine_94 小时前
前端埋点从入门到企业实践:手写一个Demo + 主流方案对比
前端·埋点