从零依赖到全场景:Maska输入掩码库完全指南(2025版)
你还在为输入格式化烦恼吗?用户输入的电话号码格式混乱、日期格式千奇百怪、信用卡号难以阅读?Maska——这款零依赖的输入掩码库,用3KB大小解决所有输入格式化难题。本文将带你从基础安装到高级定制,掌握99%场景的输入处理方案,包括Vue/React/Alpine多框架集成、动态掩码逻辑和性能优化技巧。
读完本文你将获得:
- 3种安装方式的环境适配指南
- 10+常用掩码场景的代码模板
- 4大框架的集成最佳实践
- 自定义令牌与动态掩码的高级实现
- 9个常见问题的解决方案
项目概述:为什么选择Maska?
Maska是一个轻量级(~3KB gziped)零依赖的输入掩码库,支持Vue.js、Alpine.js、Svelte和原生JavaScript。其核心优势在于:
与同类库相比,Maska具有明显优势:
| 特性 | Maska | 传统jQuery掩码 | Vue-The-Mask |
|---|---|---|---|
| 依赖 | 无 | jQuery | Vue |
| 大小 | 3KB | 15KB+ | 8KB |
| 框架支持 | 多框架 | jQuery | Vue-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使用简洁的掩码语法,由静态字符和令牌组成:
- 静态字符:直接显示的固定字符(如
-、(、)) - 令牌:匹配特定类型字符的占位符(如
#代表数字)
默认令牌系统
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 | 可选令牌 | #00 | 1 | 1 |
| multiple | 匹配多个字符直到下一个令牌 | A A | abcde | ABC DE |
| repeated | 可重复令牌 | 999 | 1234 | 1234 |
框架集成:全场景适配方案
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) |
|---|---|---|---|
| 整数 | 123456 | 123,456 | 123.456 |
| 2位小数 | 123456 | 123,456.00 | 123.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都能提供优雅的解决方案。
立即行动:
- 在你的项目中尝试集成Maska
- 分享本文给有需要的团队成员
- 关注项目更新,获取最新特性
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



