@ruan-feiyang/front-end-utils
v1.0.3
Published
前端常用工具库 - 集成浏览器判断、字符串处理、日期处理、对象处理、验证函数等常用工具
Downloads
111
Maintainers
Readme
@ruan-feiyang/front-end-utils
前端常用工具库 - 集成浏览器判断、字符串处理、日期处理、对象处理、验证函数等常用工具。
安装
npm install @ruan-feiyang/front-end-utils使用方法
ES6 模块导入
// 方式1:按需导入特定模块
import { browser, string, date, validate, func, storage } from '@ruan-feiyang/front-end-utils';
// 方式2:导入所有模块(默认导出)
import utils from '@ruan-feiyang/front-end-utils';
// 使用示例:utils.browser.isChrome()
// 方式3:直接导入特定工具
import { isChrome, isMobile } from '@ruan-feiyang/front-end-utils/browser';
import { format, fromNow } from '@ruan-feiyang/front-end-utils/date';
import { trim, capitalize } from '@ruan-feiyang/front-end-utils/string';CommonJS 模块导入
// 方式1:导入所有模块
const utils = require('@ruan-feiyang/front-end-utils');
// 使用示例:utils.browser.isChrome()
// 方式2:导入特定模块
const { browser, string, date } = require('@ruan-feiyang/front-end-utils');浏览器直接使用(UMD)
<script src="https://unpkg.com/@ruan-feiyang/front-end-utils/dist/index.umd.js"></script>
<script>
// 全局变量 window.frontEndUtils
console.log(window.frontEndUtils.browser.isChrome());
console.log(window.frontEndUtils.string.trim(' hello '));
</script>工具模块
browser - 浏览器判断
import { browser } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { isChrome, isMobile } from '@ruan-feiyang/front-end-utils/browser';
browser.isChrome() // 判断是否为 Chrome 浏览器
browser.isFirefox() // 判断是否为 Firefox 浏览器
browser.isSafari() // 判断是否为 Safari 浏览器
browser.isEdge() // 判断是否为 Edge 浏览器
browser.isIE() // 判断是否为 IE 浏览器
browser.isMobile() // 判断是否为移动端
browser.isWechat() // 判断是否为微信浏览器
browser.isIOS() // 判断是否为 iOS
browser.isAndroid() // 判断是否为 Android
browser.getBrowserName() // 获取浏览器名称: 'Chrome', 'Firefox', 'Safari', 'Edge', 'IE', 'Unknown'
browser.getBrowserVersion() // 获取浏览器版本号
// 示例
if (browser.isChrome()) {
console.log('您正在使用 Chrome 浏览器');
}
if (browser.isMobile()) {
console.log('移动端设备');
}string - 字符串处理
import { string } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { trim, capitalize } from '@ruan-feiyang/front-end-utils/string';
// 基本处理
string.trim(' hello ') // 去除两端空白: 'hello'
string.trimAll('a b c') // 去除所有空白: 'abc'
string.escapeHtml('<div>test</div>') // 转义 HTML: '<div>test</div>'
string.unescapeHtml('<div>test</div>') // 反转义 HTML: '<div>test</div>'
// 格式转换
string.capitalize('hello world') // 首字母大写: 'Hello world'
string.camelCase('hello-world') // 驼峰命名: 'helloWorld'
string.camelCase('hello_world test') // 驼峰命名: 'helloWorldTest'
string.snakeCase('helloWorld') // 下划线命名: 'hello_world'
string.kebabCase('helloWorld') // 中划线命名: 'hello-world'
// 截断与处理
string.truncate('这是一段很长的文本需要截断', 10) // 截断: '这是一段很长...'
string.truncate('Short text', 20) // 不截断: 'Short text'
// 脱敏处理
string.hideMobile('13812345678') // 隐藏手机号: '138****5678'
string.maskMobile('13812345678') // 默认中间脱敏: '138****5678'
string.maskMobile('13812345678', { mode: 'prefix' }) // 前置可见: '*******5678'
string.maskMobile('13812345678', { mode: 'suffix' }) // 后置可见: '138*******'
string.maskMobile('13812345678', { mode: 'all' }) // 全部脱敏: '***********'
string.maskMobile('13812345678', { mode: 'middle', visiblePrefix: 4, visibleSuffix: 3 }) // 自定义可见位数: '1381***678'
string.hideIdCard('110101199001011234') // 隐藏身份证: '110101********1234'
// 示例
const userMobile = '13812345678';
console.log(`用户手机号:${string.hideMobile(userMobile)}`); // 用户手机号:138****5678
const htmlContent = '<script>alert("xss")</script>';
const safeContent = string.escapeHtml(htmlContent); // <script>alert("xss")</script>date - 日期处理
import { date } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { format, fromNow } from '@ruan-feiyang/front-end-utils/date';
// 日期格式化
date.format(new Date()) // 默认格式: '2024-01-01 10:30:00'
date.format(new Date(), 'YYYY/MM/DD') // 自定义格式: '2024/01/01'
date.format(new Date(), 'YYYY年MM月DD日 HH:mm') // 中文格式: '2024年01月01日 10:30'
date.format(1700000000000, 'YYYY-MM-DD') // 时间戳格式化: '2023-11-15'
// 相对时间
date.fromNow(Date.now() - 3600000) // '1小时前'
date.fromNow(Date.now() - 86400000) // '1天前'
date.fromNow(Date.now() - 3000) // '刚刚'
// 日期范围
date.getWeekStart() // 获取本周开始日期(周一)
date.getWeekStart(new Date('2024-01-15')) // 获取指定日期所在周的开始日期
date.getMonthStart() // 获取本月开始日期
date.getMonthStart(new Date('2024-06-15')) // 获取指定日期所在月的开始日期
// 日期比较
date.isSameDay(new Date('2024-01-01'), new Date('2024-01-01 14:30')) // true
date.isSameDay(new Date('2024-01-01'), new Date('2024-01-02')) // false
// 示例
const now = new Date();
console.log(`当前时间:${date.format(now)}`);
console.log(`发布时间:${date.fromNow(now.getTime() - 7200000)}`); // 2小时前
const orderDate = new Date('2024-01-15 14:30:00');
if (date.isSameDay(orderDate, new Date())) {
console.log('这是今天的订单');
}object - 对象处理
import { object } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { deepClone, merge } from '@ruan-feiyang/front-end-utils/object';
// 深拷贝
const original = { a: 1, b: { c: 2 }, d: new Date() };
const cloned = object.deepClone(original); // 完全独立的副本
console.log(cloned === original); // false
console.log(cloned.b === original.b); // false
// 合并对象
const base = { name: '张三', age: 25 };
const updated = object.merge(base, { age: 26, city: '北京' });
console.log(updated); // { name: '张三', age: 26, city: '北京' }
// 支持多个源对象
const user = { name: '张三' };
const result = object.merge(user, { age: 25 }, { city: '北京' }, { email: '[email protected]' });
console.log(result); // { name: '张三', age: 25, city: '北京', email: '[email protected]' }
// 获取嵌套值
const data = { user: { profile: { name: '张三', age: 25 } } };
object.get(data, 'user.profile.name') // '张三'
object.get(data, 'user.profile.email') // undefined
object.get(data, 'user.profile.email', '[email protected]') // '[email protected]'
object.get(data, 'user.address.city', '未知') // '未知'
// 设置嵌套值
const obj = {};
object.set(obj, 'user.profile.name', '张三');
console.log(obj.user.profile.name); // '张三'
// 创建嵌套结构
const config = {};
object.set(config, 'database.host', 'localhost');
object.set(config, 'database.port', 3306);
object.set(config, 'app.name', 'MyApp');
console.log(config);
// {
// database: { host: 'localhost', port: 3306 },
// app: { name: 'MyApp' }
// }
// 示例
const originalUser = {
id: 1,
name: '张三',
profile: {
email: '[email protected]',
address: {
city: '北京'
}
}
};
// 安全修改
const modifiedUser = object.deepClone(originalUser);
object.set(modifiedUser, 'profile.address.city', '上海');
console.log(originalUser.profile.address.city); // '北京'(保持不变)
console.log(modifiedUser.profile.address.city); // '上海'
// 安全读取
const email = object.get(originalUser, 'profile.email', '未知邮箱');
const phone = object.get(originalUser, 'profile.phone', '未知电话');
console.log(email, phone); // '[email protected]', '未知电话'validate - 验证函数
import { validate } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { isMobile, isEmail } from '@ruan-feiyang/front-end-utils/validate';
// 手机号验证
validate.isMobile('13812345678') // true
validate.isMobile('02812345678') // false(区号格式)
validate.isMobile('1381234567') // false(位数不足)
validate.isMobile('19812345678') // true(198号段)
// 邮箱验证
validate.isEmail('[email protected]') // true
validate.isEmail('[email protected]') // true
validate.isEmail('test@example') // false(缺少域名后缀)
validate.isEmail('test example.com') // false(缺少@符号)
// 身份证验证
validate.isIdCard('110101199001011234') // true(18位)
validate.isIdCard('11010119900101123X') // true(末尾X)
validate.isIdCard('110101900101123') // true(15位)
validate.isIdCard('11010119900101123') // false(17位)
// URL 验证
validate.isUrl('https://example.com') // true
validate.isUrl('http://www.example.com/path') // true
validate.isUrl('example.com') // true(自动补全协议)
validate.isUrl('ftp://example.com') // false(仅支持 http/https)
// IP 地址验证
validate.isIPv4('192.168.1.1') // true
validate.isIPv4('255.255.255.255') // true
validate.isIPv4('192.168.1.256') // false(超出范围)
validate.isIPv4('192.168.1') // false(格式错误)
// 中文名验证
validate.isChineseName('张三') // true
validate.isChineseName('张三丰') // true
validate.isChineseName('张') // false(太短)
validate.isChineseName('张三张三张三张三张') // false(太长)
validate.isChineseName('John') // false(非中文)
// 密码强度验证
validate.checkPasswordStrength('123456') // 'weak'(纯数字)
validate.checkPasswordStrength('abcdef') // 'weak'(纯字母)
validate.checkPasswordStrength('Abc123') // 'medium'(字母+数字,长度6)
validate.checkPasswordStrength('Abc123!') // 'strong'(字母+数字+特殊字符,长度7)
validate.checkPasswordStrength('Abcdefg123!@#') // 'strong'(混合字符,长度12)
// 示例 - 表单验证
function validateUserForm(formData) {
const errors = {};
if (!formData.name || !validate.isChineseName(formData.name)) {
errors.name = '请输入2-10位中文姓名';
}
if (!formData.mobile || !validate.isMobile(formData.mobile)) {
errors.mobile = '请输入有效的手机号';
}
if (!formData.email || !validate.isEmail(formData.email)) {
errors.email = '请输入有效的邮箱地址';
}
if (!formData.password) {
errors.password = '请输入密码';
} else {
const strength = validate.checkPasswordStrength(formData.password);
if (strength === 'weak') {
errors.password = '密码强度太弱,请使用字母、数字和特殊字符组合';
}
}
return { isValid: Object.keys(errors).length === 0, errors };
}
// 使用示例
const formData = {
name: '张三',
mobile: '13812345678',
email: '[email protected]',
password: 'Abc123!'
};
const result = validateUserForm(formData);
console.log(result.isValid); // true
console.log(result.errors); // {}func - 函数工具
import { func } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { debounce, throttle } from '@ruan-feiyang/front-end-utils/func';
// 防抖(debounce)
// 在事件被触发n秒后执行函数,如果在这n秒内又被触发,则重新计时
const searchInput = document.getElementById('search');
const handleSearch = (event) => {
console.log('搜索:', event.target.value);
// 发送搜索请求...
};
const debouncedSearch = func.debounce(handleSearch, 300);
searchInput.addEventListener('input', debouncedSearch);
// 示例:输入框实时搜索,避免频繁请求
const searchApi = (keyword) => {
console.log(`搜索关键词: ${keyword}`);
// fetch(`/api/search?q=${keyword}`)...
};
const debouncedSearchApi = func.debounce(searchApi, 500);
document.getElementById('search-input').addEventListener('input', (e) => {
debouncedSearchApi(e.target.value);
});
// 节流(throttle)
// 在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效
const handleScroll = () => {
console.log('滚动位置:', window.scrollY);
};
const throttledScroll = func.throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);
// 示例:窗口resize事件
const handleResize = () => {
console.log('窗口大小:', window.innerWidth, window.innerHeight);
// 更新布局...
};
const throttledResize = func.throttle(handleResize, 100);
window.addEventListener('resize', throttledResize);
// 柯里化(curry)
// 将多参数的函数转换成一系列单参数函数
const add = (a, b, c) => a + b + c;
const curriedAdd = func.curry(add);
// 使用方式
const add5 = (b, c) => curriedAdd([5, b, c]);
console.log(add5(3, 4)); // 12
// 或直接调用
console.log(curriedAdd([1, 2, 3])); // 6
// 一次性函数(once)
// 确保函数只执行一次,后续调用返回undefined或第一次的结果
const initializeApp = () => {
console.log('应用初始化完成');
return 'initialized';
};
const initializeOnce = func.once(initializeApp);
console.log(initializeOnce()); // '应用初始化完成',返回 'initialized'
console.log(initializeOnce()); // undefined(不再执行)
console.log(initializeOnce()); // undefined
// 示例:支付按钮防重复点击
const handlePayment = () => {
console.log('支付请求发送...');
// 发送支付请求...
return 'payment_sent';
};
const safePayment = func.once(handlePayment);
document.getElementById('pay-button').addEventListener('click', () => {
const result = safePayment();
if (result) {
console.log('支付处理中...');
} else {
console.log('请勿重复点击');
}
});
// 组合使用示例
class SearchComponent {
constructor() {
this.search = func.debounce(this._performSearch.bind(this), 300);
this.initialize = func.once(this._initialize.bind(this));
}
_performSearch(keyword) {
console.log(`执行搜索: ${keyword}`);
// 实际搜索逻辑
}
_initialize() {
console.log('组件初始化');
// 初始化逻辑
}
onInput(keyword) {
this.initialize(); // 只初始化一次
this.search(keyword); // 防抖搜索
}
}
// 使用
const searchComponent = new SearchComponent();
searchComponent.onInput('react'); // 初始化 + 防抖搜索
searchComponent.onInput('react hooks'); // 只触发防抖搜索number - 数字处理
number.formatThousands(1234567) // 千分位: '1,234,567'
number.padZero(5, 2) // 补零: '05'
number.round(3.14159, 2) // 四舍五入: 3.14
number.randomInt(1, 100) // 随机整数
number.toChinese(123) // 数字转中文: '一百二十三'array - 数组处理
array.unique([1, 2, 2, 3]) // 去重: [1, 2, 3]
array.shuffle([1, 2, 3]) // 乱序
array.groupBy(items, 'category') // 分组
array.sortBy(items, 'age', 'asc') // 排序
array.flat([1, [2, 3]], 1) // 扁平化
array.difference([1, 2, 3], [2]) // 差集: [1, 3]
array.intersection([1, 2, 3], [2, 3]) // 交集: [2, 3]storage - localStorage
import { storage } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { set, get } from '@ruan-feiyang/front-end-utils/storage';
// 设置数据(自动 JSON 序列化)
storage.set('user', { name: '张三', age: 25 });
storage.set('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
storage.set('settings', { theme: 'dark', language: 'zh-CN' });
// 获取数据(自动 JSON 反序列化)
const user = storage.get('user'); // { name: '张三', age: 25 }
const token = storage.get('token'); // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
const settings = storage.get('settings'); // { theme: 'dark', language: 'zh-CN' }
// 获取不存在的键(返回默认值)
const cart = storage.get('cart', []); // [](默认值)
const history = storage.get('history'); // null(无默认值)
// 检查是否存在
if (storage.has('user')) {
console.log('用户信息已保存');
}
// 删除数据
storage.remove('token'); // 删除 token
storage.remove('tempData'); // 删除临时数据
// 清空所有数据
// storage.clear(); // 谨慎使用,会清空所有 localStorage
// 示例:用户会话管理
class UserSession {
private static readonly USER_KEY = 'user_session';
private static readonly TOKEN_KEY = 'auth_token';
static login(userData: { id: number; name: string; email: string }, token: string) {
storage.set(this.USER_KEY, userData);
storage.set(this.TOKEN_KEY, token);
}
static logout() {
storage.remove(this.USER_KEY);
storage.remove(this.TOKEN_KEY);
}
static getCurrentUser() {
return storage.get<{ id: number; name: string; email: string }>(this.USER_KEY);
}
static getToken() {
return storage.get<string>(this.TOKEN_KEY);
}
static isLoggedIn() {
return storage.has(this.USER_KEY) && storage.has(this.TOKEN_KEY);
}
}
// 使用示例
UserSession.login(
{ id: 1, name: '张三', email: '[email protected]' },
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
);
console.log(UserSession.isLoggedIn()); // true
console.log(UserSession.getCurrentUser()); // { id: 1, name: '张三', email: '[email protected]' }
UserSession.logout();
console.log(UserSession.isLoggedIn()); // false
// 示例:购物车管理
class ShoppingCart {
private static readonly CART_KEY = 'shopping_cart';
static addItem(item: { id: number; name: string; price: number; quantity: number }) {
const cart = storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
const existingItem = cart.find(i => i.id === item.id);
if (existingItem) {
existingItem.quantity += item.quantity;
} else {
cart.push(item);
}
storage.set(this.CART_KEY, cart);
return cart;
}
static removeItem(itemId: number) {
const cart = storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
const filteredCart = cart.filter(item => item.id !== itemId);
storage.set(this.CART_KEY, filteredCart);
return filteredCart;
}
static getCart() {
return storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
}
static clearCart() {
storage.set(this.CART_KEY, []);
}
static getTotal() {
const cart = this.getCart();
return cart.reduce((total, item) => total + (item.price * item.quantity), 0);
}
}
// 使用示例
ShoppingCart.addItem({ id: 1, name: '商品A', price: 100, quantity: 2 });
ShoppingCart.addItem({ id: 2, name: '商品B', price: 200, quantity: 1 });
console.log(ShoppingCart.getCart());
// [
// { id: 1, name: '商品A', price: 100, quantity: 2 },
// { id: 2, name: '商品B', price: 200, quantity: 1 }
// ]
console.log(`总价:${ShoppingCart.getTotal()}`); // 总价:400
ShoppingCart.removeItem(1);
console.log(ShoppingCart.getCart()); // [{ id: 2, name: '商品B', price: 200, quantity: 1 }]sessionStorage - 会话存储
sessionStorage.set('key', value) // 设置
sessionStorage.get('key') // 获取
sessionStorage.remove('key') // 删除
sessionStorage.clear() // 清空
sessionStorage.has('key') // 是否存在cache - 内存缓存
cache.set('key', value, ttl) // 设置缓存,ttl=秒数
cache.get('key') // 获取
cache.remove('key') // 删除
cache.clear() // 清空
cache.has('key') // 是否存在
cache.keys() // 所有缓存键
cache.cleanup() // 清理过期缓存withCache - 带缓存的异步函数
const data = await withCache('key', () => fetchApi(), 300)
// 自动缓存结果,避免重复请求cacheBatch - 批量缓存操作
cacheBatch.getMultiple(['key1', 'key2']) // 批量获取
cacheBatch.setMultiple({ k1: v1, k2: v2 }) // 批量设置
cacheBatch.removeMultiple(['key1']) // 批量删除cookie
cookie.set('name', 'value', 7) // 设置
cookie.get('name') // 获取
cookie.remove('name') // 删除其他工具
copyToClipboard('text') // 复制到剪贴板
downloadFile('content', 'file.txt') // 下载文件
formatMoney(1234.56) // 金额格式化: '¥1,234.56'
formatFileSize(1024 * 1024) // 文件大小: '1.00 MB'
getFileExtension('file.txt') // 获取扩展名: 'txt'
generateUUID() // 生成 UUID
sleep(1000) // 等待指定毫秒url - URL 工具
import { url } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { encode, decode } from '@ruan-feiyang/front-end-utils/url';
// URL 编码
url.encode('测试 & 数据') // 编码: '%E6%B5%8B%E8%AF%95%20%26%20%E6%95%B0%E6%8D%AE'
// URL 解码
url.decode('%E6%B5%8B%E8%AF%95') // 解码: '测试'
// 解析 URL 参数
url.parseParams('https://example.com?name=张三&age=25') // { name: '张三', age: '25' }
// 构建 URL 参数
url.buildParams({ name: '张三', age: '25' }) // 'name=%E5%BC%A0%E4%B8%89&age=25'
// 获取 URL 中的指定参数
url.getParam('name', 'https://example.com?name=张三&age=25') // '张三'
// 从 URL 中移除指定参数
url.removeParams('https://example.com?name=张三&age=25', ['age']) // 'https://example.com?name=张三'
// 示例:处理 URL 参数
const currentUrl = window.location.href;
const params = url.parseParams(currentUrl);
console.log('当前页面参数:', params);
// 构建带参数的 URL
const baseUrl = 'https://api.example.com';
const queryParams = { page: '1', limit: '10', keyword: '测试' };
const fullUrl = `${baseUrl}?${url.buildParams(queryParams)}`;
console.log('完整 URL:', fullUrl);page - 页面工具
page.scrollToTop() // 滚动到顶部
page.goBack() // 回到上一页
page.reload() // 刷新页面
page.getQueryParam('id') // 获取 URL 参数
page.getAllQueryParams() // 获取所有 URL 参数
page.getHash() // 获取锚点device - 设备工具
import { device } from '@ruan-feiyang/front-end-utils';
// 或直接导入:import { getNetworkType, isTouchDevice } from '@ruan-feiyang/front-end-utils/device';
// 获取网络类型
device.getNetworkType() // 'wifi', '4g', '3g', '2g', 'unknown'
// 注意:需要浏览器支持 navigator.connection
// 检测触摸设备
device.isTouchDevice() // true(支持触屏)/ false
// 获取设备像素比
device.getDevicePixelRatio() // 1, 1.5, 2, 3(Retina 显示)
// 获取屏幕尺寸
device.getScreenWidth() // 屏幕宽度(像素)
device.getScreenHeight() // 屏幕高度(像素)
// 获取窗口尺寸
device.getWindowWidth() // 可视区域宽度(像素)
device.getWindowHeight() // 可视区域高度(像素)
// 示例:响应式设计
function checkDeviceCapabilities() {
const capabilities = {
isMobile: device.isTouchDevice() && device.getScreenWidth() < 768,
isTablet: device.isTouchDevice() && device.getScreenWidth() >= 768 && device.getScreenWidth() < 1024,
isDesktop: !device.isTouchDevice() || device.getScreenWidth() >= 1024,
pixelRatio: device.getDevicePixelRatio(),
networkType: device.getNetworkType(),
screenSize: {
width: device.getScreenWidth(),
height: device.getScreenHeight()
},
windowSize: {
width: device.getWindowWidth(),
height: device.getWindowHeight()
}
};
return capabilities;
}
// 使用示例
const caps = checkDeviceCapabilities();
if (caps.isMobile) {
console.log('移动端设备,启用移动端优化');
// 加载移动端组件...
} else if (caps.isTablet) {
console.log('平板设备,启用平板布局');
// 加载平板组件...
} else {
console.log('桌面端设备,启用完整功能');
// 加载桌面端组件...
}
// 根据像素比优化图片
if (caps.pixelRatio >= 2) {
console.log('高分辨率屏幕,加载高清图片');
// img.src = '[email protected]';
} else {
console.log('普通分辨率屏幕,加载普通图片');
// img.src = 'image.png';
}
// 根据网络类型优化加载策略
if (caps.networkType === '4g' || caps.networkType === 'wifi') {
console.log('高速网络,加载高质量资源');
// 加载高清视频、大图等
} else {
console.log('低速网络,加载轻量资源');
// 加载低质量图片、压缩资源等
}更多工具模块
除了上述主要模块外,库还包含以下实用工具:
数组处理 (array)
array.unique()- 数组去重array.shuffle()- 数组乱序array.groupBy()- 按属性分组array.sortBy()- 按属性排序array.flat()- 数组扁平化array.difference()- 数组差集array.intersection()- 数组交集
数字处理 (number)
number.formatThousands()- 千分位格式化number.padZero()- 数字补零number.round()- 四舍五入number.randomInt()- 随机整数number.toChinese()- 数字转中文
Cookie 操作 (cookie)
cookie.set()- 设置 Cookiecookie.get()- 获取 Cookiecookie.remove()- 删除 Cookie
缓存管理 (cache)
cache.set()- 设置内存缓存cache.get()- 获取缓存cache.remove()- 删除缓存cache.clear()- 清空缓存cache.has()- 检查缓存是否存在cache.keys()- 获取所有缓存键cache.cleanup()- 清理过期缓存withCache()- 带缓存的异步函数cacheBatch- 批量缓存操作
页面工具 (page)
page.scrollToTop()- 滚动到顶部page.goBack()- 回到上一页page.reload()- 刷新页面page.getQueryParam()- 获取 URL 参数page.getAllQueryParams()- 获取所有 URL 参数page.getHash()- 获取锚点
URL 工具 (url)
url.encode()- URL 编码url.decode()- URL 解码url.parseParams()- 解析 URL 参数url.buildParams()- 构建 URL 参数url.getParam()- 获取 URL 中的指定参数url.removeParams()- 从 URL 中移除指定参数
杂项工具 (misc)
copyToClipboard()- 复制到剪贴板downloadFile()- 下载文件formatMoney()- 金额格式化formatFileSize()- 文件大小格式化getFileExtension()- 获取文件扩展名generateUUID()- 生成 UUIDsleep()- 等待指定毫秒
TypeScript 支持
本库完全使用 TypeScript 编写,提供完整的类型定义:
import { browser, string, date } from '@ruan-feiyang/front-end-utils';
// 类型安全的使用
const isChrome: boolean = browser.isChrome();
const trimmed: string = string.trim(' hello ');
const formattedDate: string = date.format(new Date());
// 泛型支持
interface User {
id: number;
name: string;
email: string;
}
const user: User = { id: 1, name: '张三', email: '[email protected]' };
const clonedUser: User = object.deepClone(user);开发指南
本地开发
# 克隆仓库
git clone <repository-url>
cd front_end_utils
# 安装依赖
npm install
# 开发模式(监听文件变化)
npm run dev
# 构建生产版本
npm run build
# 运行测试
npm test项目结构
src/
├── index.ts # 主入口文件,导出所有模块
├── browser.ts # 浏览器判断工具
├── string.ts # 字符串处理工具
├── date.ts # 日期处理工具
├── object.ts # 对象处理工具
├── validate.ts # 验证函数工具
├── func.ts # 函数工具
├── number.ts # 数字处理工具
├── array.ts # 数组处理工具
├── storage.ts # localStorage 工具
├── sessionStorage.ts # sessionStorage 工具
├── cache.ts # 缓存管理工具
├── cookie.ts # Cookie 操作工具
├── misc.ts # 杂项工具
├── page.ts # 页面工具
├── device.ts # 设备工具
└── url.ts # URL 工具添加新工具
- 在
src/目录下创建新的模块文件 - 实现工具函数并导出
- 在
src/index.ts中导出新模块 - 运行测试确保功能正常
- 更新 README.md 文档
构建与发布
构建项目
npm run build构建产物位于 dist/ 目录,包含:
- CommonJS 格式 (
.js) - ES Module 格式 (
.esm.js) - TypeScript 类型定义 (
.d.ts)
发布到 npm
# 登录 npm
npm login
# 更新版本号
npm version patch # 或 minor、major
# 发布
npm publish --access public测试
项目使用 Jest 进行单元测试:
# 运行所有测试
npm test
# 运行特定测试文件
npm test -- string.test.ts
# 查看测试覆盖率
npm test -- --coverage贡献指南
- Fork 项目仓库
- 创建功能分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add some amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
许可证
MIT License
联系方式
- 项目地址:GitHub Repository
- 问题反馈:GitHub Issues
- npm 包:@ruan-feiyang/front-end-utils
