vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3全局自动大写转换

Vue3实现全局自动大写转换的两种方案

作者:云吞王

本文介绍了在Vue项目中使输入框内容自动转为大写的两种方案:一种是自定义指令v-input-uppercase,适用于对特定输入框进行精细化控制;另一种是全局插件,适用于全站所有输入框,推荐使用,两种方案均能处理中文输入法兼容问题,合并成一个插件可同时实现两个功能

做业务系统时,车牌号、零件号、订单号……各种编号字段都需要大写。后端存大写、前端也显示大写,但用户打字时往往习惯输入小写,每次都要等表单报错才知道改。

与其让用户"试错",不如在前端直接帮用户转大写——体验好,后端压力也小。本文分享一套完整方案:自定义指令精准控制 + 全局插件一次搞定。

方案一:自定义指令v-input-uppercase

适合对特定输入框做精细化控制。

创建指令文件

src/directives/inputUppercase.js

const globalUppercaseConfig = {
  defaultEnabled: true,
  processedInputs: new WeakSet(),
  disabledInputs: new WeakSet()
};

export default {
  mounted(el, binding) {
    const inputElement = el.querySelector('.el-input__inner')
      || el.querySelector('input')
      || el.querySelector('textarea');
    if (!inputElement) return;

    const config = binding.value || {};
    const enabled = config.enabled !== false;

    if (!enabled) {
      globalUppercaseConfig.disabledInputs.add(el);
      return;
    }
    if (globalUppercaseConfig.processedInputs.has(el)) return;
    globalUppercaseConfig.processedInputs.add(el);

    let isComposing = false;

    const toUpperCase = () => {
      if (isComposing || !inputElement.value) return;
      const oldValue = inputElement.value;
      const newValue = oldValue.toUpperCase();
      if (oldValue !== newValue) {
        inputElement.value = newValue;
        inputElement.dispatchEvent(new Event('input', { bubbles: true }));
      }
    };

    if (inputElement.value) toUpperCase();
    inputElement.addEventListener('input', toUpperCase);
    inputElement.addEventListener('paste', () => setTimeout(toUpperCase, 10));
    inputElement.addEventListener('compositionstart', () => { isComposing = true; });
    inputElement.addEventListener('compositionend', () => {
      isComposing = false;
      setTimeout(toUpperCase, 10);
    });

    el._toUpperCase = toUpperCase;
    el._inputElement = inputElement;
  },

  beforeUnmount(el) {
    if (el._inputElement && el._toUpperCase) {
      el._inputElement.removeEventListener('input', el._toUpperCase);
      el._inputElement.removeEventListener('paste', el._toUpperCase);
    }
    globalUppercaseConfig.processedInputs.delete(el);
  }
};

export { globalUppercaseConfig };

注册指令

// src/main.js
import uppercase from './directives/inputUppercase.js'

app.directive('input-uppercase', uppercase)

使用

<!-- 自动大写 -->
<el-input v-model="plateNo" v-input-uppercase placeholder="请输入车牌号" />
<!-- 某些字段不需要转大写 -->
<el-input v-model="name" v-input-uppercase="{ enabled: false }" />

方案二:全局插件(推荐)

一个插件,覆盖所有 el-input / el-textarea / el-select,无需逐个添加指令。

创建插件文件

src/plugins/globalUppercase.js

import { globalUppercaseConfig } from '../directives/inputUppercase.js';

// 排除某些页面(如登录页不需要大写)
const globalUppercasePluginConfig = {
  excludedPaths: ['/home/login', '/qp/tableModuSet']
};

export const GlobalUppercasePlugin = {
  install(app) {
    app.mixin({
      mounted() {
        this.$nextTick(() => {
          if (!this.$el || typeof this.$el.querySelectorAll !== 'function') return;

          const currentPath = window.location.hash || window.location.pathname;
          if (globalUppercasePluginConfig.excludedPaths.some(p => currentPath.includes(p))) return;

          const applyTo = (el) => {
            if (globalUppercaseConfig.processedInputs.has(el)) return;

            const actualInput = el.querySelector('.el-input__inner')
              || el.querySelector('input')
              || el.querySelector('textarea')
              || (['INPUT', 'TEXTAREA'].includes(el.tagName) ? el : null);
            if (!actualInput) return;

            let isComposing = false;
            const toUpperCase = () => {
              if (isComposing || !actualInput.value) return;
              const newVal = actualInput.value.toUpperCase();
              if (actualInput.value !== newVal) {
                actualInput.value = newVal;
                actualInput.dispatchEvent(new Event('input', { bubbles: true }));
              }
            };

            if (actualInput.value) toUpperCase();
            actualInput.addEventListener('input', toUpperCase);
            actualInput.addEventListener('paste', () => setTimeout(toUpperCase, 10));
            actualInput.addEventListener('compositionstart', () => { isComposing = true; });
            actualInput.addEventListener('compositionend', () => {
              isComposing = false;
              setTimeout(toUpperCase, 10);
            });

            globalUppercaseConfig.processedInputs.add(el);
            el._toUpperCase = toUpperCase;
            el._inputElement = actualInput;
          };

          // 处理 el-input
          this.$el.querySelectorAll('.el-input').forEach(applyTo);
          // 处理 el-textarea
          this.$el.querySelectorAll('.el-textarea').forEach(applyTo);

          // 处理 el-select(搜索模式下的输入框)
          this.$el.querySelectorAll('.el-select').forEach(el => {
            const selectInput = el.querySelector('.el-select__input');
            if (selectInput) applyTo(selectInput);
          });
        });
      },

      beforeUnmount() {
        if (!this.$el) return;
        this.$el.querySelectorAll('.el-input, .el-textarea, .el-select').forEach(el => {
          if (el._inputElement && el._toUpperCase) {
            el._inputElement.removeEventListener('input', el._toUpperCase);
            el._inputElement.removeEventListener('paste', el._toUpperCase);
          }
          globalUppercaseConfig.processedInputs.delete(el);
        });
      }
    });
  }
};

export { globalUppercasePluginConfig };

注册插件

// src/main.js
import { GlobalUppercasePlugin } from './plugins/globalUppercase.js'

app.use(GlobalUppercasePlugin)

完成! 全站所有输入框自动大写,用户输入 abc123 → 直接显示 ABC123

两种方案对比

自定义指令全局插件
适用范围单个输入框全站
控制粒度精准全局 + 路径排除
支持组件el-input / input / textareael-input / el-textarea / el-select
注册方式app.directive()app.use()

和单引号禁止方案的对比

单引号禁止大写转换
核心操作replace(/'/g, '') 删除toUpperCase() 转换
行为输入时被阻止输入后自动转换
默认触发时机input + blurinput
特殊处理中文输入法中文输入法

两套方案代码结构几乎一致,如果你两个功能都要,完全可以合并成一个插件,通过配置项切换行为。

合并成一套插件

export const GlobalInputFilterPlugin = {
  install(app, options = {}) {
    const { mode = 'uppercase' } = options; // 'uppercase' | 'noQuote' | 'both'

    app.mixin({
      mounted() {
        this.$nextTick(() => {
          // ...统一的处理逻辑
          const transform = (val) => {
            if (mode === 'uppercase') return val.toUpperCase();
            if (mode === 'noQuote') return val.replace(/'/g, '');
            if (mode === 'both') return val.toUpperCase().replace(/'/g, '');
            return val;
          };
          // ...
        });
      }
    });
  }
};

// 使用
app.use(GlobalInputFilterPlugin, { mode: 'both' })

总结

以上就是Vue3实现全局自动大写转换的两种方案的详细内容,更多关于Vue3全局自动大写转换的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文