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

主要功能

  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
相关推荐
Heo11 小时前
Vue3.4中diff算法核心梳理
前端·javascript·面试
惜.己11 小时前
前端笔记(二)
前端·笔记
O***p60411 小时前
前端的“复杂性红线”:如何在超大型应用时代构建可持续演进的前端架构?
前端·架构
腾讯TNTWeb前端团队11 小时前
hel+发布了,一起体验原生跨端js模块联邦
前端
幸运小圣11 小时前
【Vue3】 中 ref 与 reactive:状态与模型的深入理解
前端·javascript·vue.js
叁两11 小时前
教你快速从Vue 开发者 → React开发者转变!
前端·vue.js·react.js
吴敬悦12 小时前
Claude Code 使用的命令行 UI 库: ink(使用 react 编写命令行界面)
前端·react.js
yinuo12 小时前
前端跨页面通讯终极指南⑦:ServiceWorker 用法全解析
前端
1024肥宅12 小时前
JavaScript 性能与优化:数据结构和算法
前端·数据结构·算法
沐风。5612 小时前
TypeScript
前端·javascript·typescript