1
0
Files
frost-zx.github.io/docs/content/collection-javascript-code.md
2025-10-13 10:20:34 +08:00

918 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "「合集」常用的 JavaScript 代码"
date: 2025-03-16T22:02:06Z
lastmod: 2025-03-16T22:02:33Z
tags: [合集,代码片段,Web 前端,JavaScript]
---
# 「合集」常用的 JavaScript 代码
## document
#### 焦点不在当前窗口时改变标题
```javascript
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
document.title = '焦点不在当前窗口';
} else {
document.title = '焦点在当前窗口';
}
});
```
#### 解除离开页面检测
```javascript
document.hasFocus = function () {
return true;
};
```
#### 使网页内容body可编辑
**开启**
```javascript
document.body.contentEditable = 'true';
document.designMode = 'on';
```
```javascript
(function () {
let items = document.querySelectorAll('iframe');
for (let i = 0; i < items.length; i++) {
try {
items[i].contentDocument.body.contentEditable = 'true';
items[i].contentDocument.designMode = 'on';
} catch (err) {
console.log(err);
}
}
})();
```
**关闭**
```javascript
document.body.contentEditable = 'false';
document.designMode = 'off';
```
```javascript
(function () {
let items = document.querySelectorAll('iframe');
for (let i = 0; i < items.length; i++) {
try {
items[i].contentDocument.body.contentEditable = 'false';
items[i].contentDocument.designMode = 'off';
} catch (err) {
console.log(err);
}
}
})();
```
---
## function
#### Blob 转 DataURL
```javascript
/**
* @description 转换 Blob 为 DataURL
* @param {Blob} blob
* @returns {Promise<{ dataURL: string; success: boolean; }>}
*/
function blobToDataURL(blob) {
return new Promise((resolve) => {
let fileReader = new FileReader();
// 处理读取异常
fileReader.onerror = function () {
resolve({
dataURL: '',
success: false,
});
};
// 处理读取完成
fileReader.onload = function () {
resolve({
dataURL: fileReader.result,
success: true,
});
};
// 开始读取
fileReader.readAsDataURL(blob);
});
}
```
#### 查找元素的 Vue 对象
```javascript
/**
* @typedef {object} FunctionResult
* @property {boolean} state 是否查找成功
* @property {HTMLElement} element Vue 对象所在的元素
* @property {object} data 找到的 Vue 对象
* @property {object[]} parents 父 Vue 对象
*/
/**
* @description 查找元素的 Vue 对象
* @param {HTMLElement} el 需要查找的元素
* @returns {FunctionResult} 返回查找结果信息
*/
function findElementVue(el) {
/** @type {FunctionResult} */
const result = {
state: false,
element: null,
data: null,
parents: [],
};
const attrName = '__vue__';
// 查找属性
while (el) {
const data = el[attrName];
if (data) {
result.state = true;
result.element = el;
result.data = data;
break;
} else {
el = el.parentElement;
}
}
// 查找父对象
if (result.state) {
let attrName = '$parent';
let parent = result.data[attrName];
while (parent) {
result.parents.push(parent);
parent = parent[attrName];
}
}
return result;
}
```
#### 查找字符 `char` 在 `str` 中第 `num` 次出现的位置
```javascript
function findChar(str = '', char = '', num = 1) {
var index = str.indexOf(char);
num = num - 1;
if (num > 0) {
for (var i = 0; i < num; i++) {
index = str.indexOf(char, index + 1);
}
}
return index;
}
```
#### 处理过渡效果
```javascript
// https://www.npmjs.com/package/d3-ease
/**
* @description 处理过渡效果
* @param {object} opts
* @param {number} opts.duration 时长(毫秒)
* @param {Function} opts.easeFn 过渡计算函数
* @param {Function} opts.onStop 结束时回调
* @param {Function} opts.onTick 进行时回调
* @returns {Promise<boolean>}
*/
function easeHandler(opts = {}) {
const {
duration = 0,
easeFn = easeLinear,
onStop = null,
onTick = null,
} = opts;
const isValid = (
(typeof duration === 'number' && duration >= 0) &&
(typeof easeFn === 'function') &&
(onStop ? typeof onStop === 'function' : true) &&
(onTick ? typeof onTick === 'function' : true)
);
if (!isValid) {
console.error('处理失败:参数错误');
return Promise.resolve(false);
}
// 时长为 0直接结束
if (duration === 0) {
onTick && onTick(1);
onStop && onStop();
return Promise.resolve(true);
}
const sTime = Date.now();
const eTIme = sTime + duration;
return new Promise((resolve) => {
const fn = function () {
try {
const curr = Date.now();
const diff = Math.min(duration, curr - sTime);
const p = parseFloat((diff / duration).toFixed(3));
const n = parseFloat(easeFn(p).toFixed(3));
if (curr < eTIme) {
// [继续]
onTick && onTick(n);
requestAnimationFrame(fn);
} else {
// [结束]
onTick && onTick(1);
onStop && onStop();
resolve(true);
}
} catch (error) {
console.error('处理失败:');
console.error(error);
resolve(false);
}
};
// 开始
fn();
});
}
```
#### 对有符号整型、无符号整型、浮点型、十六进制、二进制的数据处理
参考https://www.cnblogs.com/zhouheblog/p/13578012.html
```javascript
// 十六进制字符串转有符号整型(支持 S8、S16、S32
function hexToInt(hex) {
if (!hex) {
return NaN;
}
if (hex.length % 2 !== 0) {
hex = '0' + hex;
}
let num = parseInt(hex, 16);
let max = Math.pow(2, hex.length / 2 * 8);
if (num > max / 2 - 1) {
num = num - max;
}
return num;
}
```
```javascript
// 十六进制字符串转无符号整型(支持 U8、U16、U32
parseInt(str, 16);
```
```javascript
/**
* @description 合并对象lodash.mergeWith
* - 将会修改目标对象
* - 若来源属性为数组,将会直接替换
* - 若目标属性为对象,但来源属性为 `null`,则跳过
* @template TObject
* @param {TObject} obj 合并目标
* @param {TObject} src 合并来源
* @returns {TObject}
*/
function mergeObject(obj, src) {
return mergeWith(obj, src, function (objValue, srcValue) {
if (Array.isArray(srcValue)) {
return srcValue;
} else if (srcValue === null && isObject(objValue)) {
return objValue;
}
});
}
```
#### 格式化时间
```javascript
/**
* @description 格式化时间
* @param {(number|string|Date)} [time] 要格式化的时间(默认当前)
* @param {string} [format] 需要的格式(默认 yyyy-mm-dd hh:ii:ss
* @returns {string} 格式化后的时间
*/
function formatTime(time = new Date(), format = 'yyyy-mm-dd hh:ii:ss') {
let timeType = typeof time;
/** @type {Date} */
let dateObj = null;
if (timeType == 'number' || timeType == 'string') {
dateObj = new Date(time);
} else if (timeType == 'object') {
dateObj = time;
}
// 时间信息
let timeInfo = {
// 年月日
y: dateObj.getFullYear(),
m: dateObj.getMonth() + 1,
d: dateObj.getDate(),
// 时分秒
h: dateObj.getHours(),
i: dateObj.getMinutes(),
s: dateObj.getSeconds(),
};
// 格式占位符正则
let formatReg = {
y: /y+/g,
m: /m+/g,
d: /d+/g,
h: /h+/g,
i: /i+/g,
s: /s+/g,
};
for (let key in formatReg) {
// 正则匹配
let matched = format.match(formatReg[key]);
// 获取对应的时间
let timeValue = String(timeInfo[key]);
// 无匹配结果
if (!matched) {
continue;
}
// 根据匹配结果(位数)进行替换
matched.forEach(function (v) {
let tLength = timeValue.length;
let vLength = v.length;
// 长度不足,补零
if (tLength < vLength) {
timeValue = timeValue.padStart(v.length, '0');
}
// 长度超出,截取
// if (tLength > vLength) {
// timeValue = timeValue.substring(tLength - vLength);
// }
// 替换对应的值
format = format.replace(v, timeValue);
});
}
return format;
}
```
#### 获取随机的十六进制色
```javascript
/** 获取随机的十六进制色 */
function getHEXColor() {
var codes = [
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
];
var colors = ['#'];
for (let i = 0; i < 6; i++) {
let index = Math.floor(Math.random() * 16);
colors.push(codes[index]);
}
return colors.join('');
}
```
#### 获取元素的边界信息
```javascript
/**
* @description 获取元素的边界信息(当前元素必须在父元素内)
* @param {Element} curr 当前 DOM 元素
* @param {Element} parent 父 DOM 元素
*/
function getBoundaryInfo(curr, parent) {
if (!curr || !parent) {
console.error('获取失败,缺少参数!');
return null;
}
var result = {};
var currRect = curr.getBoundingClientRect();
var parentRect = parent.getBoundingClientRect();
// 当前元素四角坐标和宽高
result.curr = {
x0: currRect.left,
x1: currRect.right,
y0: currRect.top,
y1: currRect.bottom,
w: currRect.width,
h: currRect.height,
};
// 父元素四角坐标
result.parent = {
x0: parentRect.left,
x1: parentRect.right,
y0: parentRect.top,
y1: parentRect.bottom,
w: parentRect.width,
h: parentRect.height,
};
// 距离
result.distance = {
top: result.curr.y0 - result.parent.y0,
bottom: result.parent.y1 - result.curr.y1,
left: result.curr.x0 - result.parent.x0,
right: result.parent.x1 - result.curr.x1,
};
return result;
}
```
#### 获取元素的坐标信息
```javascript
/**
* @description 获取元素的坐标信息(四个角以及宽高)
* @param {Element} element DOM 元素
*/
function getElemPosInfo(element) {
if (!element) {
console.error('获取失败,缺少参数!');
return null;
}
let rect = element.getBoundingClientRect();
let data = {
x0: rect.left,
x1: rect.right,
y0: rect.top,
y1: rect.bottom,
w: rect.width,
h: rect.height,
};
return data;
}
```
#### 获取月份第一天和最后一天的时间戳
```javascript
/**
* @description 获取月份第一天和最后一天的时间戳
* @param {number} year 年份
* @param {number} month 月份
* @returns `{ start: 第一天, end: 最后一天 }`
*/
function getTimestampOfMonth(year, month) {
var start = new Date(year, month - 1, 1)
var end = new Date(year, month, 0);
var time = {
start: start.getTime(),
end: end.getTime()
};
return time;
}
```
#### 获取坐标下方的元素
```javascript
/**
* @description 获取坐标下方的元素(从子元素到父元素)
* @param {number} x 横坐标
* @param {number} y 纵坐标
*/
function elemsFromPoint(x, y) {
if (x === undefined || y === undefined) {
return [];
}
x = Math.floor(x);
y = Math.floor(y);
let item = document.elementFromPoint(x, y);
let items = [];
if (item) {
items.push(item);
} else {
return [];
}
while (item.parentElement) {
item = item.parentElement;
items.push(item);
}
return items;
};
```
#### 计算字符串的字符数
```javascript
/**
* @description 计算字符串的字符数(数字英文字母 +1其他 +3
* @param {string} str 被检测的字符串
* @returns {number} 字符数
*/
function calcChars(str) {
var reg = /[0-9a-zA-Z]/;
var sum = 0;
for (let i in str) {
if (reg.test(str.charAt(i))) {
sum += 1;
} else {
sum += 3;
}
}
return sum;
}
```
#### 加减法精度
```javascript
/**
* @description 加减法精度
* @param {string} type 类型plus、sub
* @param {number} [num1] 数值1默认为 0
* @param {number} [num2] 数值2默认为 0
* @returns {(number|null)} 返回两个数值相加或相减后的结果
*/
function accPlusAndSub(type, num1 = 0, num2 = 0) {
var decimalsNum1 = (String(num1).split('.')[1] || '').length;
var decimalsNum2 = (String(num2).split('.')[1] || '').length;
var decimalsMax = Math.max(decimalsNum1, decimalsNum2);
var multiplies = Math.pow(10, decimalsMax);
if (type === 'plus') {
return ((num1 * multiplies + num2 * multiplies) / multiplies);
} else if (type === 'sub') {
return ((num1 * multiplies - num2 * multiplies) / multiplies);
} else {
return null;
}
}
```
#### 检测用户是否离开页面
```javascript
/**
* @description 检测用户是否离开页面(一秒检测一次)
* @param {object} [options] 配置选项
* @param {function} [options.onblur] 用户离开页面时的回调函数
* @param {function} [options.onfocus] 用户返回页面时的回调函数
* @param {string} [options.blurDelay] 设定用户离开页面多久后才调用 onblur
* - 单位为秒
* - 默认 0
* @param {string} [options.timerName] 定时器名称
* - 用于 setInterval()
* - 默认 tCheckPageBlur
*/
function checkPageBlur(options) {
var config = {
onblur: null,
onfocus: null,
blurDelay: 0,
timerName: 'tCheckPageBlur',
};
Object.assign(config, options);
var timerName = config.timerName; // 定时器名称
var checkDelay = 0; // 延时
var blurTriggered = false; // 标记状态
clearInterval(window[timerName]);
window[timerName] = setInterval(function () {
var isFocus = document.hasFocus();
if (isFocus && blurTriggered) {
// 在页面且触发过 blur
blurTriggered = false;
checkDelay = 0;
try {
config.onfocus && (config.onfocus());
} catch (err) {
console.error('[检测] 回调函数 onfocus 出错\n', err);
}
} else if (!isFocus && !blurTriggered) {
// 不在页面且未触发 blur
if (checkDelay >= config.blurDelay) {
blurTriggered = true;
checkDelay = 0;
try {
config.onblur && (config.onblur());
} catch (err) {
console.error('[检测] 回调函数 onblur 出错\n', err);
}
} else {
checkDelay += 1;
}
}
}, 1000);
}
// 调用
checkPageBlur({
onblur: function () {
console.log('[检测] 用户离开页面');
},
onfocus: function () {
console.log('[检测] 用户返回页面');
},
});
```
#### 解析 URL 地址的参数(?=...)为一个对象
```javascript
function queriesToObj(url = '') {
var split = url.split('?')[1];
var arr = split.split('&');
var obj = {};
arr.forEach(function (item) {
var kv = item.split('=');
obj[kv[0]] = kv[1];
});
return obj;
}
```
#### 矩形碰撞检测
```javascript
/**
* @description 矩形碰撞检测
* @param {Element} elemA 当前元素
* @param {Element} elemB 目标元素
* @param {boolean} [checkAside] 是否包含边缘碰撞,默认包含
* @returns {object} `{ error: 是否检测失败, hit: 是否碰撞 }`
*/
function rectColisionCheck(elemA, elemB, checkAside = true) {
const result = {
error: false,
hit: false,
};
if (!(elemA && elemB)) {
console.error('缺少参数');
result.error = true;
return result;
}
const rectA = elemA.getBoundingClientRect();
const rectB = elemB.getBoundingClientRect();
if (checkAside) {
result.hit = !(
rectA.bottom < rectB.top ||
rectA.left > rectB.right ||
rectA.top > rectB.bottom ||
rectA.right < rectB.left
);
} else {
result.hit = !(
rectA.bottom <= rectB.top ||
rectA.left >= rectB.right ||
rectA.top >= rectB.bottom ||
rectA.right <= rectB.left
);
}
return result;
}
```
#### 设置事件对象属性
```javascript
/**
* @description 设置事件对象属性
* @param {Eveny} ev 事件对象
* @param {object} props 要设置的属性
*/
function setEvProps(ev, props = {}) {
if (ev) {
for (let key in props) {
Object.defineProperty(ev, key, {
configurable: true,
enumerable: true,
get: function () {
return props[key];
},
});
}
}
}
```
#### 通过点路径访问对象属性
```javascript
/**
* @description 通过点路径访问对象属性
* @param {object} obj
* @param {string} path
*/
function getObjValue(obj, path = '') {
if (typeof obj !== 'object') {
console.error('访问失败,参数 obj 错误!');
return;
}
if (typeof path !== 'string') {
console.error('访问失败,参数 path 错误!');
return;
}
if (path === '') {
return obj;
}
return path.split('.').reduce((a, b) => {
return (a === undefined ? a : a[b]);
}, obj);
}
```
#### 暂停执行代码一段时间
```javascript
/**
* @description 暂停执行代码一段时间
* @param {number} [time] 时长(毫秒),默认 1000
* @returns {Promise} Promise
*/
function sleep(time = 1000) {
return new Promise(function (resolve) {
setTimeout(() => {
resolve();
}, time);
});
}
await sleep(1000);
```
#### 字符串转文件
```javascript
/**
* @description 字符串转文件
* @param {string} data 字符串数据
* @param {string} filename 文件名
* @param {string} filetype 文件类型MIME
*/
function strToFile(data = '', filename = 'export.txt', filetype = 'text/plain') {
// 转为 Blob
var strToBlob = new Blob([data], { type: filetype });
// URL 对象兼容性处理
var urlObject = window.URL || window.webkitURL || window;
// 创建对象 URL
var blobURL = urlObject.createObjectURL(strToBlob);
// 创建 a 元素
var aElem = document.createElement('a');
// 设置属性
aElem.classList.add('hidden');
aElem.download = filename;
aElem.href = blobURL;
aElem.target = '_blank';
// 添加元素
document.body.appendChild(aElem);
// 模拟点击
aElem.click();
// 移除元素
aElem.remove();
// 释放对象
urlObject.revokeObjectURL(blobURL);
}
```
#### 转换 JSON 为 SQLite 插入语句
```javascript
/**
* @description 生成 SQLite 插入语句
* @param {string} t 表名
* @param {string[]} k 键名列表
* @param {(number|string)[]} v 值列表
*/
function getSqlInsert(t, k, v) {
k = k.map(val => `"${val}"`);
v = v.map(val => (val === null ? 'NULL' : `'${val}'`));
return `INSERT INTO "${t}" (${k.join(', ')}) VALUES (${v.join(', ')})`;
}
/**
* @description 转换 JSON 为 SQLite 语句INSERT
* @param {string} table 表名
* @param {Record<string, number|string>[]} data
* @param {string[]} [keys] 属性过滤
*/
function jsonToSql(table, data, keys) {
try {
const result = [];
const filter = Array.isArray(keys);
if (!table) {
throw new Error('缺少 table 参数');
}
if (!Array.isArray(data)) {
throw new Error('缺少 data 参数');
}
for (let i = 0; i < data.length; i++) {
let item = data[i];
let keys = [];
let values = [];
let sql = '';
// 记录 key 和 value
if (filter) {
for (let key in item) {
if (keys.includes(key)) {
keys.push(key);
values.push(item[key]);
}
}
} else {
for (let key in item) {
keys.push(key);
values.push(item[key]);
}
}
// 生成 SQL 插入语句
sql = getSqlInsert(table, keys, values);
result.push(sql);
}
return result;
} catch (error) {
console.error('转换失败:');
console.error(error);
return null;
}
}
```