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

主要功能

  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
相关推荐
Restart-AHTCM6 分钟前
前端核心框架vue之(路由篇3/5)
前端·javascript·vue.js
段振轩17 分钟前
Docker nginx容器部署前端项目。
前端·nginx·docker
让时光到此为止。1 小时前
vue的首屏优化是怎么做的
前端·javascript·vue.js
温宇飞1 小时前
CSS 中如何处理空白字符
前端
dengzhenyue1 小时前
矩形碰撞检测
开发语言·前端·javascript
llq_3501 小时前
为什么 npm view yarn version 显示 1.22.22?
前端
aesthetician2 小时前
ReactFlow:构建交互式节点流程图的完全指南
前端·流程图·react
neo_dowithless2 小时前
多语言维护太痛苦?我自研了一个翻译自动化 CLI 工具
前端·ai编程
小徐_23332 小时前
老乡鸡也开源?我用 Trae SOLO 做了个像老乡鸡那样做饭小程序!
前端·trae
荒诞英雄2 小时前
菠萝滞销,帮帮我们(多个APP实例间pinia混乱)
前端·架构