jsly
v3.1.7
Published
js工具库
Readme
jsly
一些常用的js函数工具
安装
npm 安装
npm install jslycdn 引入
<script src="https://cdn.jsdelivr.net/npm/jsly@<version>/dist/index.umd.js"></script>引入后,全局对象 Jsly 将包含所有工具函数。
使用示例
防抖函数
import { debounce } from 'jsly'
// 防抖函数示例
const handler = debounce(() => console.log('Debounced!'), 300)
window.addEventListener('resize', handler)
节流函数
import { throttle } from 'jsly'
const handler = throttle(() => console.log('Throttled!'), 300)
window.addEventListener('scroll', handler)
SHA-256 加密
import { sha256 } from 'jsly'
const hash = sha256('hello world')
console.log(hash)
UUID SHA-256 哈希
import { randomHash } from 'jsly'
// 默认 v1 UUID
console.log(randomHash())
// v1 UUID
console.log(randomHash('v1'))
// v2 UUID
console.log(randomHash('v2'))
// v3 UUID
console.log(randomHash('v3'))
// v4 UUID
console.log(randomHash('v4'))
// v5 UUID
console.log(randomHash('v5'))
浏览器指纹 ID
import { generateBrowserId } from 'jsly'
const browserId = generateBrowserId()
console.log(browserId) // 64 位 SHA-256 哈希
对象构建 FormData
import { buildObjFormData } from 'jsly'
const formData = buildObjFormData({
name: 'John',
files: [file1, file2],
date: new Date(),
extra: null
})
console.log(formData)
剪贴板复制
import { copyToClipboard, copyByClipboardAPI, copyByExecCommand } from 'jsly'
// 1️⃣ 自动选择最佳方案复制
await copyToClipboard('Hello World!')
console.log('Text copied to clipboard!')
// 2️⃣ 直接使用 Clipboard API(现代浏览器推荐)
try {
await copyByClipboardAPI('Hello Clipboard API!')
console.log('Copied via Clipboard API!')
} catch (err) {
console.error('Clipboard API failed:', err)
}
// 3️⃣ 通过 textarea + execCommand(兼容旧浏览器)
try {
await copyByExecCommand('Hello execCommand!')
console.log('Copied via execCommand!')
} catch (err) {
console.error('execCommand failed:', err)
}
字符串与对象命名转换
import { camelToSnake, snakeToCamel, toggleConvertCase, convertKeys } from 'jsly'
// 字符串转换
console.log(camelToSnake('myVariable')) // my_variable
console.log(snakeToCamel('my_variable')) // myVariable
console.log(toggleConvertCase('myVariable')) // my_variable
console.log(toggleConvertCase('my_variable')) // myVariable
// 对象键名转换(默认只转换首层)
console.log(convertKeys({ user_name: 'Tom', user_info: { phone_number: '123' } }, 'camel'))
// => { userName: 'Tom', userInfo: { phone_number: '123' } }
// 递归转换所有层级
console.log(convertKeys({ user_name: 'Tom', user_info: { phone_number: '123' } }, 'camel', true))
// => { userName: 'Tom', userInfo: { phoneNumber: '123' } }
console.log(convertKeys({ userName: 'Tom', userInfo: { phoneNumber: '123' } }, 'snake'))
// => { user_name: 'Tom', user_info: { phoneNumber: '123' } }
console.log(convertKeys({ userName: 'Tom', userInfo: { phoneNumber: '123' } }, 'snake', true))
// => { user_name: 'Tom', user_info: { phone_number: '123' } }
对象差异对比
import { shallowDiff, deepDiff } from 'jsly'
const oldObj = { a: 1, b: { x: 10, y: 20 } }
const newObj = { a: 2, b: { x: 10, y: 30 } }
// 第一层差异
console.log(shallowDiff(oldObj, newObj)) // { a: 2, b: { x: 10, y: 30 } }
// 深度差异
console.log(deepDiff(oldObj, newObj)) // { a: 2, b: { x: 10, y: 30 } }
// 深度差异最小化
console.log(deepDiff(oldObj, newObj, true)) // { a: 2, b: { y: 30 } }
事件总线
import { $bus } from 'jsly'
// 订阅事件
$bus.on('test', data => console.log('Received:', data))
// 触发事件
$bus.emit('test', { a: 1 })
// 一次性事件
$bus.once('onceEvent', () => console.log('This runs only once'))
// 取消订阅
function listener() {}
$bus.off('test', listener)
// 移除所有监听器
$bus.removeAllListeners()
文本关键词高亮(highlightKeyword)
高亮文本中匹配的关键词,支持不区分大小写匹配,并允许自定义标签与样式。
import { highlightKeyword } from 'jsly'
const text = '泡泡音乐是一款非常好用的音乐播放器'
const result = highlightKeyword(text, '音乐')
console.log(result)
// => '泡泡<span style="background-color: #ff0;color: #001;">音乐</span>是一款非常好用的<span style="background-color: #ff0;color: #001;">音乐</span>播放器'
自定义标签与样式
highlightKeyword('Hello World', 'world', {
tag: 'mark',
bgColor: '#000',
color: '#0f0'
})
配置说明
| 参数 | 类型 | 默认值 | 说明 |
|------|------|---------|------|
| text | string | 必填 | 原始文本 |
| keyword | string | 必填 | 要高亮的关键词(大小写不敏感) |
| config.tag | string | 'span' | 包裹关键词的标签名 |
| config.bgColor | string | '#ff0' | 背景颜色 |
| config.color | string | '#001' | 文本颜色 |
基于 requestAnimationFrame 的定时器(rafInterval)
使用 requestAnimationFrame 实现类似 setInterval 的效果。 更适合动画、轮播、游戏循环等需要与浏览器帧同步的场景。
import { rafInterval } from 'jsly'
// 每秒执行一次
const stop = rafInterval(() => {
console.log('tick')
}, 1000)
// 停止执行
stop()在 Vue 中使用
import { rafInterval } from 'jsly'
import { onMounted, onUnmounted } from 'vue'
let stop
onMounted(() => {
stop = rafInterval(() => {
console.log('frame update')
}, 16) // 约 60fps
})
onUnmounted(() => {
stop()
})基轮询函数(poll)
用于按固定间隔重复执行任务,直到:
- 返回结果为 truthy
- 超时
- 手动停止 适用于接口状态查询、等待资源加载、检测条件成立等场景。
import { poll } from 'jsly'
// 轮询接口直到 ready === true
const { promise, stop } = poll(
async () => {
const res = await fetch('/api/status').then(r => r.json())
return res.ready && res
},
{
interval: 2000, // 每 2 秒执行一次
timeout: 10000 // 10 秒超时
}
)
promise
.then(data => {
console.log('成功:', data)
})
.catch(err => {
console.error('轮询失败:', err)
})
// 如需手动停止
// stop()