从零依赖到全场景:Maska输入掩码库完全指南(2025版)

从零依赖到全场景:Maska输入掩码库完全指南(2025版)

【免费下载链接】maska Simple zero-dependency input mask for Vue.js and vanilla JS. 【免费下载链接】maska 项目地址: https://gitcode.com/gh_mirrors/ma/maska

你还在为输入格式化烦恼吗?用户输入的电话号码格式混乱、日期格式千奇百怪、信用卡号难以阅读?Maska——这款零依赖的输入掩码库,用3KB大小解决所有输入格式化难题。本文将带你从基础安装到高级定制,掌握99%场景的输入处理方案,包括Vue/React/Alpine多框架集成、动态掩码逻辑和性能优化技巧。

读完本文你将获得:

  • 3种安装方式的环境适配指南
  • 10+常用掩码场景的代码模板
  • 4大框架的集成最佳实践
  • 自定义令牌与动态掩码的高级实现
  • 9个常见问题的解决方案

项目概述:为什么选择Maska?

Maska是一个轻量级(~3KB gziped)零依赖的输入掩码库,支持Vue.js、Alpine.js、Svelte和原生JavaScript。其核心优势在于:

mermaid

与同类库相比,Maska具有明显优势:

特性Maska传统jQuery掩码Vue-The-Mask
依赖jQueryVue
大小3KB15KB+8KB
框架支持多框架jQueryVue-only
自定义令牌完整支持有限基础支持
数字模式内置需要自定义需插件

快速开始:5分钟上手

环境准备

Maska支持多种安装方式,可根据项目环境选择:

npm安装(推荐)
npm install maska --save
CDN引入(国内加速)
<!-- 原生JS -->
<script src="https://cdn.jsdelivr.net/npm/maska@3/dist/cdn/maska.js"></script>

<!-- Vue集成 -->
<script src="https://cdn.jsdelivr.net/npm/maska@3/dist/cdn/vue.js"></script>

<!-- Alpine集成 -->
<script src="https://cdn.jsdelivr.net/npm/maska@3/dist/cdn/alpine.js"></script>
Import Map(现代浏览器)
<script type="importmap">
  {
    "imports": {
      "maska": "https://cdn.jsdelivr.net/npm/maska@3/dist/maska.mjs"
    }
  }
</script>

第一个掩码:电话号码格式化

原生JavaScript实现

<input type="text" data-maska="+1 (###) ###-####" id="phone">

<script>
  import { MaskInput } from "maska"
  new MaskInput("#phone")
</script>

Vue实现

<template>
  <input v-maska="'+1 (###) ###-####'">
</template>

<script setup>
import { vMaska } from "maska/vue"
</script>

效果演示: 输入1234567890将自动格式化为+1 (123) 456-7890

核心概念:掩码语法与令牌系统

掩码基础语法

Maska使用简洁的掩码语法,由静态字符和令牌组成:

  • 静态字符:直接显示的固定字符(如-()
  • 令牌:匹配特定类型字符的占位符(如#代表数字)

mermaid

默认令牌系统

Maska提供3种默认令牌:

令牌描述正则表达式示例应用
#数字/[0-9]/电话号码
@字母/[a-zA-Z]/姓名
*字母数字/\w/用户名

自定义令牌

通过tokens选项创建自定义令牌:

// 日期格式令牌:DD/MM/YYYY
new MaskInput("input", {
  mask: "DD/MM/YYYY",
  tokens: {
    D: { pattern: /[0-3]/, optional: true },
    M: { pattern: /[0-1]/, optional: true },
    Y: { pattern: /[0-9]/ }
  }
})

令牌修饰符

修饰符作用示例掩码输入输出
optional可选令牌#0011
multiple匹配多个字符直到下一个令牌A AabcdeABC DE
repeated可重复令牌99912341234

框架集成:全场景适配方案

Vue集成

基础用法

<template>
  <input v-maska="maskOptions" v-model="phone">
</template>

<script setup>
import { ref } from 'vue'
import { vMaska } from 'maska/vue'

const phone = ref('')
const maskOptions = {
  mask: '+1 (###) ###-####',
  eager: true
}
</script>

双向绑定高级用法

<template>
  <input 
    v-maska:unmaskedValue.unmasked="'+1 (###) ###-####'" 
    v-model="maskedValue"
  >
  
  <p>格式化值: {{ maskedValue }}</p>
  <p>原始值: {{ unmaskedValue }}</p>
</template>

<script setup>
import { ref } from 'vue'
import { vMaska } from 'maska/vue'

const maskedValue = ref('')
const unmaskedValue = ref('')

defineExpose({ unmaskedValue })
</script>

Alpine.js集成

<div x-data="{ phone: '' }">
  <input 
    x-maska="'+1 (###) ###-####'" 
    x-model="phone"
  >
  
  <p x-text="phone"></p>
</div>

Svelte集成

<script>
  import { maska } from 'maska/svelte'
  let phone = ''
</script>

<input use:maska={'+1 (###) ###-####'} bind:value={phone}>
<p>{phone}</p>

原生JavaScript

<input type="text" id="creditCard">

<script>
  import { MaskInput } from 'maska'
  
  const mask = new MaskInput('#creditCard', {
    mask: '####-####-####-####',
    onMaska: (detail) => {
      if (detail.completed) {
        console.log('信用卡号输入完成')
      }
    }
  })
  
  // 动态更改掩码
  document.querySelector('#toggle').addEventListener('click', () => {
    mask.setOptions({ mask: '#### #### #### ####' })
  })
</script>

高级功能:解锁全场景应用

数字模式:智能货币格式化

Maska内置数字模式,支持多 locale 格式化:

<!-- 基础用法 -->
<input data-maska-number>

<!-- 高级配置 -->
<input 
  data-maska-number 
  data-maska-number-locale="de-DE" 
  data-maska-number-fraction="2"
>

JavaScript配置

new MaskInput('input', {
  number: {
    locale: 'en-US',
    fraction: 2,
    unsigned: true
  }
})

效果对比

配置输入输出(en-US)输出(de-DE)
整数123456123,456123.456
2位小数123456123,456.00123.456,00

动态掩码:智能表单适配

根据输入值自动切换掩码:

new MaskInput('input', {
  mask: (value) => {
    // 美国电话号码
    if (value.startsWith('+1')) return '+1 (###) ###-####'
    // 国际电话号码
    if (value.startsWith('+')) return '+# (###) ###-####'
    // 默认本地号码
    return '(###) ###-####'
  }
})

事件与钩子:全流程控制

事件监听

// 原生JS
input.addEventListener('maska', (e) => {
  console.log('格式化值:', e.detail.masked)
  console.log('原始值:', e.detail.unmasked)
  console.log('是否完成:', e.detail.completed)
})

// Vue
<input v-maska @maska="handleMaskChange">

处理钩子

new MaskInput('input', {
  mask: '##/##/####',
  preProcess: (value) => {
    // 移除所有非数字字符
    return value.replace(/\D/g, '')
  },
  postProcess: (value) => {
    // 自动补全当前年份
    if (value.length === 5) {
      return value + new Date().getFullYear().toString().slice(-2)
    }
    return value
  }
})

实战案例:10大场景解决方案

1. 日期输入(DD/MM/YYYY)

<input data-maska="DD/MM/YYYY" data-maska-tokens="D:[0-3]:optional|M:[0-1]:optional|Y:[0-9]">

2. 信用卡格式化

<input 
  data-maska="####-####-####-####" 
  data-maska-reversed
  oninput="formatCardType(this)"
>

<script>
function formatCardType(input) {
  const value = input.value.replace(/\D/g, '')
  if (value.startsWith('4')) {
    input.dataset.maska = '#### #### #### ####' // Visa
  } else if (value.startsWith('5')) {
    input.dataset.maska = '####-####-####-####' // MasterCard
  }
}
</script>

3. 增值税号(EU VAT)

<input data-maska="AA## #### ####" data-maska-tokens="A:[A-Z]">

4. IP地址输入

<input 
  data-maska="#00.#00.#00.#00" 
  data-maska-tokens="0:[0-9]:optional"
>

5. 货币输入(带符号)

new MaskInput('input', {
  number: {
    locale: 'en-US',
    fraction: 2
  },
  postProcess: (value) => `$${value}`
})

6. 车牌号输入(中国)

<input data-maska="A#·####A" data-maska-tokens="A:[A-Z]|#:[0-9]">

7. 时间输入(HH:MM:SS)

<input 
  data-maska="HH:MM:SS" 
  data-maska-tokens="H:[0-2]:optional|M:[0-5]:optional|S:[0-5]:optional"
>

8. 百分比输入

new MaskInput('input', {
  mask: '##0%',
  tokens: {
    0: { pattern: /[0-9]/, optional: true }
  },
  preProcess: (value) => {
    // 将百分比转换为小数存储
    return (parseFloat(value) / 100).toString()
  }
})

9. 中文身份证号

<input data-maska="##############000X" data-maska-tokens="0:[0-9]:optional|X:[0-9Xx]">

10. 动态长度邮政编码

<input data-maska="#####-####" data-maska-tokens="9:[0-9]:optional">

问题诊断:常见问题与解决方案

输入框无法获取焦点

原因:掩码初始化时机过早,DOM尚未加载完成。

解决方案

// 原生JS
document.addEventListener('DOMContentLoaded', () => {
  new MaskInput('input')
})

// Vue
onMounted(() => {
  // 确保DOM已渲染
})

与UI框架冲突(如Vuetify)

解决方案:通过选项传递所有配置,不依赖data属性:

<template>
  <v-text-field v-maska="maskOptions"></v-text-field>
</template>

<script setup>
const maskOptions = {
  mask: '+1 (###) ###-####',
  eager: true
}
</script>

数字模式在部分locale下显示异常

解决方案:手动处理初始值:

// 针对德国locale
const input = document.querySelector('input')
const initialValue = '123456.78'
input.value = new Intl.NumberFormat('de-DE', {
  minimumFractionDigits: 2
}).format(initialValue)

动态更改掩码不生效

解决方案:使用setOptions方法:

const mask = new MaskInput('input', { mask: '###' })

// 动态更新
mask.setOptions({ mask: '####-####' })

性能优化:大规模应用最佳实践

1. 延迟初始化

// 仅在输入框聚焦时初始化
document.querySelectorAll('input[data-maska]').forEach(input => {
  input.addEventListener('focus', function initMask() {
    new MaskInput(this)
    this.removeEventListener('focus', initMask)
  })
})

2. 批量处理

// 一次性初始化所有掩码
new MaskInput('[data-maska]')

3. 大型表单优化

对于超过100个输入框的大型表单:

// 使用事件委托减少监听器
document.getElementById('large-form').addEventListener('input', (e) => {
  if (e.target.hasAttribute('data-maska') && !e.target._maskInitialized) {
    new MaskInput(e.target)
    e.target._maskInitialized = true
  }
})

总结与展望

Maska作为一款零依赖的输入掩码库,通过灵活的配置和多框架支持,为各类输入格式化需求提供了轻量级解决方案。其核心优势包括:

  • 零依赖设计:降低项目复杂度和潜在冲突
  • 多框架兼容:一套逻辑适配多种前端框架
  • 强大的自定义能力:从简单令牌到复杂动态掩码
  • 优化的性能:小体积和高效处理逻辑

未来展望

  • Web Components支持
  • 更多内置掩码模板
  • 实时验证集成
  • React官方支持

学习资源

  • 官方文档:Maska文档
  • GitHub仓库:https://gitcode.com/gh_mirrors/ma/maska
  • 代码示例库:https://github.com/beholdr/maska/tree/main/demo

掌握Maska输入掩码库,将为你的用户提供更流畅的输入体验,同时减少前端开发中的格式化处理负担。无论是简单的电话号码还是复杂的动态表单,Maska都能提供优雅的解决方案。

立即行动

  1. 在你的项目中尝试集成Maska
  2. 分享本文给有需要的团队成员
  3. 关注项目更新,获取最新特性

【免费下载链接】maska Simple zero-dependency input mask for Vue.js and vanilla JS. 【免费下载链接】maska 项目地址: https://gitcode.com/gh_mirrors/ma/maska

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值