使用imaskjs实现js表单输入卡号/日期/货币等掩码的教程

1. 前言

在 Web 开发中,表单输入格式化是提升用户体验的关键环节。无论是电话号码、信用卡号还是日期,合适的格式不仅能减少用户输入错误,还能让界面更专业。本文将全面介绍 IMask.js 的使用方法,帮助你掌握表单输入格式化的精髓。

IMask.js 是一个轻量级的 JavaScript 库,用于对输入框内容进行实时格式化和验证。它具有以下特点:

  • 支持多种掩码类型:数字、日期、正则表达式、函数等
  • 实时格式化,边输入边处理
  • 支持自定义验证规则
  • 无依赖,可独立使用
  • 体积小巧,压缩后仅约 15KB
  • 支持所有现代浏览器和移动设备
  • 可与框架(React、Vue、Angular 等)无缝集成

2. 快速开始

IMask.js 提供多种安装选项:

1. CDN 引入

<script src="https://cdn.jsdelivr.net/npm/imask@6.4.3/dist/imask.min.js"></script>

2. npm 安装

npm install imask --save

然后在项目中引入:

import IMask from 'imask';

2.1. 基本用法

使用 IMask.js 非常简单,只需三步即可实现输入格式化:

  1. 创建 HTML 输入框:
<input type="text" id="phone" placeholder="请输入电话号码">
  1. 定义掩码规则并初始化:
// 获取输入框元素
const phoneInput = document.getElementById('phone');

// 定义掩码配置
const maskOptions = {
  mask: '+{86} (000) 0000-0000'
};

// 应用掩码
const mask = IMask(phoneInput, maskOptions);

这样就实现了一个中国电话号码的格式化功能,用户输入时会自动按照 +86 (XXX) XXXX-XXXX 的格式进行显示。

3. 核心掩码类型

IMask.js 支持多种掩码类型,满足不同场景的需求:

3.1. 字符串掩码(静态掩码)

适用于固定格式的输入,如电话号码、身份证号等:

// 身份证号掩码
const idCardMask = IMask(document.getElementById('id-card'), {
  mask: '000000000000000000' // 18位数字
});

// 护照号码掩码(字母+数字)
const passportMask = IMask(document.getElementById('passport'), {
  mask: 'A0000000' // 1个字母+7个数字
});

3.2. 模式掩码(动态掩码)

使用对象定义更灵活的模式:

// 支持多种电话号码格式
const phoneMask = IMask(document.getElementById('phone'), {
  mask: [
    { mask: '+{86} (000) 0000-0000' }, // 固定电话
    { mask: '+{86} 0000-0000000' },    // 另一种固定电话格式
    { mask: '+{86} 100-0000-0000' }    // 手机号码
  ]
});

3.3. 数字掩码

专门用于数字输入,支持范围限制、精度控制等:

// 价格输入(最多两位小数)
const priceMask = IMask(document.getElementById('price'), {
  mask: Number,
  min: 0,               // 最小值
  max: 10000,           // 最大值
  thousandsSeparator: ',', // 千位分隔符
  radix: '.',           // 小数点符号
  precision: 2          // 保留两位小数
});

// 整数输入(1-100)
const integerMask = IMask(document.getElementById('integer'), {
  mask: Number,
  min: 1,
  max: 100,
  precision: 0 // 不保留小数
});

3.4. 日期掩码

用于日期格式化,支持多种日期格式:

// 年月日格式
const dateMask = IMask(document.getElementById('date'), {
  mask: Date,
  pattern: 'yyyy-mm-dd', // 格式
  min: new Date(1900, 0, 1), // 最小日期
  max: new Date(2100, 11, 31), // 最大日期
  lazy: false // 不允许部分输入
});

// 月日年格式
const usDateMask = IMask(document.getElementById('us-date'), {
  mask: Date,
  pattern: 'mm/dd/yyyy',
  placeholder: 'mm/dd/yyyy'
});

3.5. 正则表达式掩码

使用正则表达式定义更复杂的格式规则:

// 邮箱掩码(简单验证)
const emailMask = IMask(document.getElementById('email'), {
  mask: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
});

// 密码掩码(至少8位,包含字母和数字)
const passwordMask = IMask(document.getElementById('password'), {
  mask: /^(?=.*[A-Za-z])(?=.*\d).{8,}$/,
  lazy: false
});

3.6. 函数掩码

通过自定义函数实现最灵活的掩码逻辑:

// 自定义函数掩码示例:只允许输入偶数
const evenNumberMask = IMask(document.getElementById('even-number'), {
  mask: function(value, masked) {
    // 只允许输入偶数
    if (value === '') return '';
    const num = parseInt(value);
    return isNaN(num) ? '' : (num % 2 === 0 ? value : value.slice(0, -1));
  }
});

4. 高级配置选项

IMask.js 提供了丰富的配置选项,让你可以精确控制输入行为:

const advancedMask = IMask(inputElement, {
  mask: '0000-00-00',
  
  // 占位符字符
  placeholderChar: '_',
  
  // 是否允许空白值
  nullable: false,
  
  // 是否使用惰性模式(允许部分输入)
  lazy: true,
  
  // 输入事件触发时机
  dispatch: 'input',
  
  // 提交时是否去除格式化字符
  unmask: true,
  
  // 定义转换规则
  prepare: function(value) {
    return value.toUpperCase(); // 自动转换为大写
  },
  
  // 验证规则
  validate: function(value) {
    return value.length === 10; // 验证长度
  }
});

5. 事件处理

IMask.js 提供了多种事件,让你可以在输入过程中执行自定义逻辑:

const mask = IMask(inputElement, {
  mask: '+{86} (000) 0000-0000'
});

// 当值发生变化时触发
mask.on('accept', () => {
  console.log('当前值(带格式):', mask.value);
  console.log('原始值(无格式):', mask.unmaskedValue);
  updateUI(mask.unmaskedValue);
});

// 当输入被拒绝时触发
mask.on('reject', (value) => {
  console.log('被拒绝的输入:', value);
  showError('输入格式不正确');
});

// 当掩码状态变化时触发
mask.on('complete', () => {
  console.log('输入已完成');
  hideError();
});

6. 与前端框架集成

IMask.js 可以与主流前端框架无缝集成:

6.1. 与 React 集成

import React, { useRef, useEffect, useState } from 'react';
import IMask from 'imask';

function PhoneInput() {
  const inputRef = useRef(null);
  const [phone, setPhone] = useState('');
  
  useEffect(() => {
    const mask = IMask(inputRef.current, {
      mask: '+{86} (000) 0000-0000',
      onAccept: () => {
        setPhone(mask.unmaskedValue);
      }
    });
    
    return () => mask.destroy(); // 组件卸载时清理
  }, []);
  
  return (
    <input
      ref={inputRef}
      type="text"
      placeholder="+86 (000) 0000-0000"
    />
  );
}

或者使用社区提供的封装组件 react-imask

npm install react-imask --save
import { IMaskInput } from 'react-imask';

function CreditCardInput() {
  return (
    <IMaskInput
      mask="0000 0000 0000 0000"
      placeholder="信用卡号"
      onAccept={(value, mask) => {
        console.log('卡号:', mask.unmaskedValue);
      }}
      // 其他输入框属性
      className="form-control"
    />
  );
}

6.2. 与 Vue 集成

<template>
  <input
    ref="dateInput"
    type="text"
    placeholder="yyyy-mm-dd"
  >
</template>

<script>
import IMask from 'imask';

export default {
  data() {
    return {
      mask: null,
      date: ''
    };
  },
  mounted() {
    this.mask = IMask(this.$refs.dateInput, {
      mask: Date,
      pattern: 'yyyy-mm-dd'
    });
    
    this.mask.on('accept', () => {
      this.date = this.mask.unmaskedValue;
    });
  },
  beforeUnmount() {
    if (this.mask) {
      this.mask.destroy();
    }
  }
};
</script>

也可以使用社区封装的 vue-imask 组件。

7. 实际应用场景

下面是一些实际应用场景:

7.1. 信用卡号格式化

<input type="text" id="credit-card" placeholder="信用卡号">
const ccMask = IMask(document.getElementById('credit-card'), {
  mask: [
    {
      mask: '0000 0000 0000 0000', // 通用信用卡格式
      regex: /^4\d{15}$|^5[1-5]\d{14}$|^3[47]\d{13}$/ // 简单验证
    }
  ],
  placeholderChar: ' ',
  onAccept: () => {
    // 验证卡类型
    const cardNumber = ccMask.unmaskedValue;
    let cardType = 'unknown';
    
    if (/^4/.test(cardNumber)) cardType = 'visa';
    else if (/^5[1-5]/.test(cardNumber)) cardType = 'mastercard';
    else if (/^3[47]/.test(cardNumber)) cardType = 'amex';
    
    console.log('卡类型:', cardType);
  }
});

7.2. 货币输入格式化

<input type="text" id="currency" placeholder="金额">
const currencyMask = IMask(document.getElementById('currency'), {
  mask: Number,
  min: 0,
  max: 1000000,
  thousandsSeparator: ',',
  radix: '.',
  precision: 2,
  // 前缀
  prefix: '¥ ',
  // 当值为0时显示空
  nullable: true
});

7.3. IP 地址输入

<input type="text" id="ip" placeholder="IP地址">
const ipMask = IMask(document.getElementById('ip'), {
  mask: [
    {
      mask: '0[0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9]',
      validate: function(value) {
        // 验证每个段是否在0-255之间
        const parts = value.split('.');
        return parts.every(part => {
          const num = parseInt(part);
          return num >= 0 && num <= 255;
        });
      }
    }
  ]
});

8. 常见问题及解决方案

下面是一些常见问题及解决方案:

8.1. 掩码与浏览器自动填充冲突

解决方案:禁用自动填充或在填充后手动更新掩码:

<input type="text" id="phone" autocomplete="off">

或者:

const mask = IMask(input, { /* 配置 */ });

// 监听输入框变化,处理自动填充
input.addEventListener('change', () => {
  mask.updateValue();
});

8.2. 输入框值通过 JavaScript 更改时不触发掩码

解决方案:使用 mask.value 而不是直接修改输入框的值:

// 错误方式
input.value = '13800138000';

// 正确方式
mask.value = '13800138000';

8.3. 移动端输入体验问题

解决方案:优化触摸设备上的输入体验:

IMask(input, {
  mask: '0000-00-00',
  // 延迟处理,避免输入抖动
  lazy: true,
  // 针对移动设备优化
  onAccept: () => {
    if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
      // 移动设备特定处理
    }
  }
});

要了解更多关于 IMask.js 的信息,可以访问其 官方文档 或者 Github仓库 获取最新的 API 参考和示例。


本次分享就到这儿啦,我是鹏多多,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

往期文章

个人主页

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲浪的鹏多多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值