Cleave.js:优雅解决输入格式化的终极方案
还在为复杂的表单输入验证和格式化头疼吗?每次都要写冗长的正则表达式来处理信用卡号、电话号码、日期等格式?Cleave.js 正是为解决这些痛点而生的强大 JavaScript 格式化库。
🎯 读完本文你能得到
- Cleave.js 核心功能全景解析
- 五大格式化场景实战代码示例
- React、Angular、Vue 三大框架集成指南
- 性能优化与最佳实践建议
- 常见问题排查与解决方案
📊 Cleave.js 核心能力矩阵
| 功能模块 | 支持格式 | 特色功能 | 适用场景 |
|---|---|---|---|
| 信用卡格式化 | Visa/MasterCard/Amex 等16+种 | 实时类型检测、严格模式 | 支付表单、电商平台 |
| 电话号码 | 全球200+国家地区 | 按需加载、国际格式 | 注册登录、用户资料 |
| 日期时间 | 多种格式组合 | 日期范围限制、时间格式 | 预约系统、生日输入 |
| 数字金额 | 千分位格式化 | 多国数字风格、小数点控制 | 财务系统、价格输入 |
| 自定义模式 | 任意分隔模式 | 灵活块配置、多重分隔符 | 序列号、验证码 |
🚀 五分钟快速上手
基础安装方式
<!-- CDN 引入 -->
<script src="https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/cleave.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cleave.js@1.6.0/dist/addons/cleave-phone.cn.js"></script>
<!-- npm 安装 -->
npm install cleave.js
基础使用示例
// 信用卡格式化
const creditCardCleave = new Cleave('#credit-card-input', {
creditCard: true,
onCreditCardTypeChanged: function(type) {
console.log('信用卡类型:', type);
}
});
// 电话号码格式化(中国)
const phoneCleave = new Cleave('#phone-input', {
phone: true,
phoneRegionCode: 'CN'
});
// 日期格式化
const dateCleave = new Cleave('#date-input', {
date: true,
datePattern: ['Y', 'm', 'd']
});
// 数字金额格式化
const numeralCleave = new Cleave('#amount-input', {
numeral: true,
numeralThousandsGroupStyle: 'thousand',
numeralDecimalScale: 2
});
🎨 五大核心功能深度解析
1. 信用卡格式化 - 智能识别与安全体验
const cleave = new Cleave('.credit-card-input', {
creditCard: true,
creditCardStrictMode: true,
delimiter: '-',
onCreditCardTypeChanged: function(type) {
// 实时更新UI显示卡类型
document.getElementById('card-type').textContent = type.toUpperCase();
}
});
// 支持的信用卡类型
const cardTypes = {
'amex': '美国运通',
'visa': 'Visa',
'mastercard': '万事达',
'unionPay': '银联',
'jcb': 'JCB',
'discover': 'Discover'
};
2. 全球电话号码 - 国际化支持
// 中国手机号格式
new Cleave('.phone-cn', {
phone: true,
phoneRegionCode: 'CN'
}); // 输出: 138 0013 8000
// 美国电话号码
new Cleave('.phone-us', {
phone: true,
phoneRegionCode: 'US'
}); // 输出: (408) 555-1234
// 自定义分隔符
new Cleave('.phone-custom', {
phone: true,
phoneRegionCode: 'CN',
delimiter: '-'
}); // 输出: 138-0013-8000
3. 日期时间格式化 - 灵活配置
// 多种日期格式
const dateFormats = [
{ pattern: ['d', 'm', 'Y'], example: '31/12/2023' },
{ pattern: ['Y', 'm', 'd'], example: '2023/12/31' },
{ pattern: ['m', 'd', 'Y'], example: '12/31/2023' },
{ pattern: ['y', 'm', 'd'], example: '23/12/31' }
];
// 带范围限制的日期
new Cleave('.date-with-range', {
date: true,
datePattern: ['Y', 'm', 'd'],
dateMin: '2020-01-01',
dateMax: '2030-12-31'
});
// 时间格式化
new Cleave('.time-input', {
time: true,
timePattern: ['h', 'm'],
timeFormat: '12'
}); // 输出: 02:30 PM
4. 数字金额处理 - 财务级精度
// 标准千分位
new Cleave('.standard-numeral', {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
}); // 1,234,567.89
// 中文万位分组
new Cleave('.chinese-numeral', {
numeral: true,
numeralThousandsGroupStyle: 'wan'
}); // 123,4567.89
// 印度数字分组
new Cleave('.indian-numeral', {
numeral: true,
numeralThousandsGroupStyle: 'lakh'
}); // 12,34,567.89
// 货币格式化
new Cleave('.currency-input', {
numeral: true,
prefix: '¥',
numeralIntegerScale: 7,
numeralDecimalScale: 2,
numeralDecimalMark: '.',
delimiter: ','
}); // ¥1,234,567.89
5. 自定义模式 - 无限可能
// 证件号码格式
new Cleave('.id-card', {
blocks: [6, 8, 4],
delimiter: ' ',
numericOnly: true
}); // 110101 19900101 1234
// 序列号格式
new Cleave('.serial-number', {
blocks: [4, 4, 4, 4],
delimiters: ['-', '-', '-'],
uppercase: true
}); // ABCD-EFGH-IJKL-MNOP
// 复杂分隔模式
new Cleave('.complex-pattern', {
blocks: [3, 2, 3, 2],
delimiters: ['.', '-', '.'],
prefix: 'PRE-'
}); // PRE-123.45-678.90
⚛️ 框架集成指南
React 组件集成
import React from 'react';
import Cleave from 'cleave.js/react';
class PaymentForm extends React.Component {
constructor(props) {
super(props);
this.state = {
cardNumber: '',
cardType: ''
};
}
handleCardChange = (event) => {
this.setState({
cardNumber: event.target.value,
rawCardNumber: event.target.rawValue
});
}
handleCardTypeChange = (type) => {
this.setState({ cardType: type });
}
render() {
return (
<div>
<Cleave
placeholder="请输入信用卡号"
options={{
creditCard: true,
onCreditCardTypeChanged: this.handleCardTypeChange
}}
onChange={this.handleCardChange}
className="form-control"
/>
{this.state.cardType && (
<div className="card-type-badge">
{this.state.cardType.toUpperCase()}
</div>
)}
</div>
);
}
}
AngularJS 指令使用
angular.module('myApp', ['cleave.js'])
.controller('FormController', function($scope) {
$scope.onCardTypeChanged = function(type) {
$scope.cardType = type;
};
$scope.creditCardOptions = {
creditCard: true,
onCreditCardTypeChanged: $scope.onCardTypeChanged
};
});
<div ng-controller="FormController">
<input type="text"
ng-model="cardNumber"
cleave="creditCardOptions"
placeholder="信用卡号">
<span ng-if="cardType">{{cardType}}</span>
</div>
Vue.js 集成方案
// 全局注册
import Cleave from 'cleave.js';
Vue.directive('cleave', {
inserted(el, binding) {
el.cleave = new Cleave(el, binding.value);
},
update(el, binding) {
if (binding.value !== binding.oldValue) {
el.cleave.destroy();
el.cleave = new Cleave(el, binding.value);
}
},
unbind(el) {
el.cleave.destroy();
}
});
<template>
<input v-cleave="phoneOptions" v-model="phoneNumber">
</template>
<script>
export default {
data() {
return {
phoneNumber: '',
phoneOptions: {
phone: true,
phoneRegionCode: 'CN'
}
};
}
};
</script>
🏗️ 架构设计与实现原理
Cleave.js 核心架构
性能优化策略
- 按需加载机制:电话号码库按国家分离,减少初始包体积
- 事件委托优化:使用 input 事件而非 keypress 事件
- 内存管理:提供 destroy() 方法清理资源
- 批量更新:避免频繁的 DOM 操作
🔧 高级配置与最佳实践
配置选项详解
const advancedConfig = {
// 基础功能
creditCard: true,
phone: true,
date: true,
numeral: true,
// 格式化选项
delimiter: '-', // 分隔符
delimiters: ['.', '-'], // 多重分隔符
blocks: [3, 3, 4], // 分组块
prefix: 'USD ', // 前缀
tailPrefix: false, // 后缀模式
// 数字处理
numeralIntegerScale: 10, // 整数位数
numeralDecimalScale: 2, // 小数位数
numeralDecimalMark: '.', // 小数点符号
numeralThousandsGroupStyle: 'thousand', // 千分位样式
// 回调函数
onValueChanged: function(e) {
console.log('格式化值:', e.target.value);
console.log('原始值:', e.target.rawValue);
},
onCreditCardTypeChanged: function(type) {
console.log('卡类型变化:', type);
},
// 高级选项
numericOnly: true, // 仅数字
uppercase: false, // 大写转换
delimiterLazyShow: true, // 延迟显示分隔符
rawValueTrimPrefix: true, // 原始值去除前缀
swapHiddenInput: false // 隐藏输入域交换
};
错误处理与边界情况
// 安全的 Cleave 实例创建
function createSafeCleave(selector, options) {
try {
const element = document.querySelector(selector);
if (!element) {
console.warn(`元素 ${selector} 未找到`);
return null;
}
return new Cleave(element, options);
} catch (error) {
console.error('Cleave 初始化失败:', error);
return null;
}
}
// 验证电话号码格式
function validatePhoneNumber(phoneValue, regionCode) {
const cleave = new Cleave({ value: phoneValue }, {
phone: true,
phoneRegionCode: regionCode
});
return cleave.getRawValue().length > 0;
}
📈 性能对比与优势分析
与传统方案对比
| 方案类型 | 开发成本 | 维护难度 | 性能表现 | 功能完整性 |
|---|---|---|---|---|
| 正则表达式 | 高 | 高 | 中 | 低 |
| 原生 JavaScript | 中 | 中 | 高 | 中 |
| jQuery 插件 | 中 | 中 | 中 | 中 |
| Cleave.js | 低 | 低 | 高 | 高 |
适用场景推荐
- 电商平台:信用卡支付、电话号码验证
- 金融系统:金额输入、数字格式化
- 企业应用:日期时间选择、自定义编码
- 移动端应用:轻量级格式化解决方案
- 多语言网站:国际化数字和电话格式
🚨 常见问题与解决方案
Q1: 如何处理动态创建的输入框?
// 使用事件委托
document.body.addEventListener('focus', function(e) {
if (e.target.matches('.format-input') && !e.target.cleave) {
e.target.cleave = new Cleave(e.target, {
creditCard: e.target.dataset.type === 'creditcard'
});
}
}, true);
Q2: 如何获取原始值进行后端验证?
const cleave = new Cleave('#input-field', options);
// 获取原始值(无格式化)
const rawValue = cleave.getRawValue();
// 在表单提交时使用
document.getElementById('myForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = {
formatted: cleave.getFormattedValue(),
raw: cleave.getRawValue()
};
// 发送到后端
});
Q3: 如何实现实时验证反馈?
const cleave = new Cleave('#input-field', {
creditCard: true,
onValueChanged: function(e) {
const isValid = validateInput(e.target.rawValue);
updateValidationUI(isValid);
}
});
function validateInput(value) {
// 自定义验证逻辑
return value.length > 0 && /^\d+$/.test(value);
}
🎯 总结与展望
Cleave.js 作为一个成熟的输入格式化解决方案,在以下几个方面表现出色:
- 功能全面:覆盖信用卡、电话、日期、数字等主要格式化场景
- 使用简单:API 设计直观,学习成本低
- 性能优异:轻量级实现,不影响页面性能
- 扩展性强:支持自定义模式和框架集成
- 维护活跃:社区支持良好,文档齐全
虽然项目已标记为 deprecated,但其设计理念和实现方式仍然值得学习和借鉴。对于新项目,建议考虑其继任者 cleave-zen,但对于现有项目的维护和升级,Cleave.js 仍然是一个可靠的选择。
无论你是前端新手还是资深开发者,Cleave.js 都能为你的表单处理工作流带来显著的效率提升和用户体验改善。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



