javascript常用操作
# 通过鼠标坐标获取当前 DOM 对象
const x = event.pageX || event.clientX + document.body.scroolLeft;
const y = event.pageY || event.clientY + document.body.scrollTop;
const dom = document.elementFromPoint(x, y);
2
3
# 处理富文本内容中的图片地址为完整地址
const baseUrl = "http://localhost";
const res = content.replace(
/<(img [^>]*)src=['"]([^'"]+)['"]([^>]*)>/gi,
function (match, p1, p2, p3) {
let url = (function () {
if (!p2) {
return "";
}
if (p2.indexOf("http") === 0 || p2.indexOf("blob:") === 0) {
return p2;
} else if (p2.indexOf("/") === 0) {
return baseUrl + p2;
}
return baseUrl + "/" + p2;
})();
var newStr = `<${p1} src="${url}" ${p3}>`;
return newStr;
},
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# input 输入为金额,保留两位小数
/** 输入 */
function onkeyup(e) {
value = value
.replace(/[^\d\.]/g, "") // 只能输入数字和小数点
.replace(/^\./g, "") // 过滤开头的小数点
.replace(/\.{2,}/g, ".") // 多个连续小数点合并为一个
.replace(".", "$#$")
.replace(/\./g, "")
.replace("$#$", ".") // 保留第一个小数点,删除其他的小数点
.replace(/^0(\d+)/, "$1") // 过滤开头的0
.replace(/^(\d+)\.(\d\d).*$/, "$1.$2"); // 保留两位小数
return value;
}
/** 失去焦点 */
function onblur(e) {
value = value
.replace(/[^\d\.]/g, "") // 只能输入数字和小数点
.replace(/^\./g, "") // 过滤开头的小数点
.replace(/\.{2,}/g, ".") // 多个连续小数点合并为一个
.replace(".", "$#$")
.replace(/\./g, "")
.replace("$#$", ".") // 保留第一个小数点,删除其他的小数点
.replace(/^0(\d+)/, "$1") // 过滤开头的0
.replace(/^(\d+)\.(\d\d).*$/, "$1.$2"); // 保留两位小数
// 输入0的时候转成空或者可自行调节 0.00 看需求
if (input.value === "0") {
input.value = "";
}
// 把 123. 的数据转成 123
if (input.value.split(".")[1] == "") {
input.value = input.value.split(".")[0];
}
return value;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 百度坐标转高德(传入经度、纬度)
function bd_decrypt(bd_lng, bd_lat) {
var X_PI = (Math.PI * 3000.0) / 180.0;
var x = bd_lng - 0.0065;
var y = bd_lat - 0.006;
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
var gg_lng = z * Math.cos(theta);
var gg_lat = z * Math.sin(theta);
return { lng: gg_lng, lat: gg_lat };
}
2
3
4
5
6
7
8
9
10
# 高德坐标转百度(传入经度、纬度)
function bd_encrypt(gg_lng, gg_lat) {
var X_PI = (Math.PI * 3000.0) / 180.0;
var x = gg_lng,
y = gg_lat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return {
bd_lat: bd_lat,
bd_lng: bd_lng,
};
}
2
3
4
5
6
7
8
9
10
11
12
13
# 监听全屏事件
window.document.addEventListener("fullscreenchange", function () {
if (document.fullscreenElement) {
console.log("进入全屏");
} else {
console.log("退出全屏");
}
});
2
3
4
5
6
7
# 将 div(页面元素)保存为图片
这里需要用到 html2canvas 库, 下载库 https://www.npmjs.com/package/html2canvas (opens new window)
html2canvas(document.querySelector("#qr")).then(function (canvas) {
var imgData = canvas.toDataURL("image/png");
var newData = imgData.replace(
/^data:image\/png/,
"data:application/octet-stream",
);
const a = document.createElement("a");
a.href = newData;
a.download = "code.png";
a.target = "_blank";
a.click();
});
2
3
4
5
6
7
8
9
10
11
12
这里推荐使用dom-to-image
/* in ES 6 */
import domtoimage from "dom-to-image";
/* in ES 5 */
var domtoimage = require("dom-to-image");
domtoimage.toPng(node);
var node = document.getElementById("my-node");
domtoimage
.toPng(node)
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error("oops, something went wrong!", error);
});
domtoimage.toBlob(node).then(function (blob) {
window.saveAs(blob, "my-node.png");
});
domtoimage.toJpeg(node, { quality: 0.95 }).then(function (dataUrl) {
var link = document.createElement("a");
link.download = "my-image-name.jpeg";
link.href = dataUrl;
link.click();
});
function filter(node) {
return node.tagName !== "i";
}
// 获取SVG数据URL,但过滤掉所有元素:
const dataUrl = await domtoimage.toSvg(node, { filter: filter });
// Uint8Array
domtoimage.toPixelData(node).then(function (pixels) {
for (var y = 0; y < node.scrollHeight; ++y) {
for (var x = 0; x < node.scrollWidth; ++x) {
pixelAtXYOffset = 4 * y * node.scrollHeight + 4 * x;
/* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
}
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 计算两个坐标点之间的直线距离
// 方法定义 lat,lng
function GetDistance(lat1, lng1, lat2, lng2) {
var radLat1 = (lat1 * Math.PI) / 180.0;
var radLat2 = (lat2 * Math.PI) / 180.0;
var a = radLat1 - radLat2;
var b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0;
var s =
2 *
Math.asin(
Math.sqrt(
Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2),
),
);
s = s * 6378.137; // EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
}
// 调用 return的距离单位为km
GetDistance(10.0, 113.0, 12.0, 114.0);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 将 Blob 转为 JSON
if (blob.type === "application/json") {
const reader = new FileReader();
reader.readAsText(blob);
reader.onload = () => {
try {
const res = JSON.parse(reader.result.toString());
this.$message.error(res.msg);
} catch (e) {
this.$message.error(e.message);
}
};
}
2
3
4
5
6
7
8
9
10
11
12
# 下载 Blob 格式文件
// blob转文件并下载
downloadFileByBlob(blob, fileName = "file") {
let blobUrl = window.URL.createObjectURL(blob) // 主要使用该方法
let link = document.createElement('a')
link.download = fileName || 'defaultName'
link.style.display = 'none'
link.href = blobUrl
// 触发点击
document.body.appendChild(link)
link.click()
// 移除
document.body.removeChild(link)
window.URL.revokeObjectURL(blobUrl)
}
// 调用
downloadFileByBlob(res.data, '活动策略数据表.xlsx')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 前端实现打印预览功能
window.print() 默认打印的 body 中的内容,也可以实现局部打印,就是将要打印的内容赋值给 body 然后再重新赋值还原
function doPrint() {
//根据div标签ID拿到div中的局部内容
bdhtml = window.document.body.innerHTML;
var jubuData = document.getElementById("printcontent").innerHTML;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML = jubuData;
//调用打印功能
window.print();
window.document.body.innerHTML = bdhtml; //重新给页面内容赋值;
return false;
}
2
3
4
5
6
7
8
9
10
11
打印事件:
- window.onbeforeprint()--打印之前做的事,在页面即将打印时触发 (在打印窗口出现前)。
- window.onafterprint()--打印之后做的事
给使用的元素加上 page-break-inside: avoid; 来解决分页截断问题
# 构建导出 CSV
let data = 'data:text/csv;charset=utf-8,';
data += ['姓名', '年龄'].join(',')+"\r\n"
[
['张三', 12],
['李四', 13]
].forEach(item => {
data += item.join(',')+"\r\n"
})
let link = document.createElement('a')
link.style.display = 'none'
link.download = fileName'
link.href = encodeURI(data)
// 触发点击
document.body.appendChild(link)
link.click()
// 移除
document.body.removeChild(link)
window.URL.revokeObjectURL(blobUrl)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 关闭微信浏览窗口
if (window.WeixinJSBridge) {
// 安卓
document.addEventListener(
"WeixinJSBridgeReady",
function () {
window.WeixinJSBridge.call("closeWindow");
},
false,
);
// ios
window.WeixinJSBridge.call("closeWindow");
}
2
3
4
5
6
7
8
9
10
11
12
# 将字节数组转换为 16 进制字符串
Array.prototype.map
.call(new Uint8Array(val), (v) => ("00" + v.toString(16)).slice(-2))
.join(" ") + " ";
2
3
# js 操作导出为 pdf
引入jspdfjs 库
const { jsPDF } = window.jspdf;
const doc = new jsPDF("", "pt", "a4");
// image=图片内容
doc.addImage(image, "PNG", 0, 0);
doc.addPage();
doc.save(".pdf");
2
3
4
5
6
# 字符串转 ArrayBuffer
stringToArrayBuffer(str) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
var array = new Int8Array(bytes.length);
for (var i = 0; i <= bytes.length; i++) {
array[i] = bytes[i];
}
return array.buffer;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 字符串转ArrayBuffer
* @param {Object} str
*/
export function strToBuf(str) {
if (!str) {
return new ArrayBuffer(0);
}
if (typeof str === "number") {
var buffer = new ArrayBuffer(1);
var dataView = new DataView(buffer);
dataView.setUint8(0, str);
return buffer;
}
var buffer = new ArrayBuffer(str.length);
var dataView = new DataView(buffer);
for (let i in str) {
dataView.setUint8(i, str[i].charCodeAt() | 0);
}
return buffer;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ArrayBuffer 转字符串
arrayBufferToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer))
}
2
3
/**
* ArrayBuffer转字符串
* @param {Object} buffer
*/
export function bufToStr(buffer) {
const uint8Array = new Uint8Array(buffer);
let str = "";
for (let i = 0; i < uint8Array.length; i++) {
str += String.fromCharCode(uint8Array[i]);
}
return str;
}
2
3
4
5
6
7
8
9
10
11
12
# 20 个「零依赖」浏览器原生能力!
# 1.ResizeObserver
精准监听任意 DOM 宽高变化,图表自适应、虚拟滚动必备。
new ResizeObserver(([e]) => chart.resize(e.contentRect.width)).observe(
chartDom,
);
2
3
# 2. IntersectionObserver
检测元素进出视口,一次搞定懒加载 + 曝光埋点,性能零损耗。
new IntersectionObserver((entrieList) =>
entrieList.forEach((e) => e.isIntersecting && loadImg(e.target)),
).observe(img);
2
3
# 3. Page Visibility
侦测标签页隐藏,自动暂停视频、停止轮询,移动端省电神器。
document.addEventListener("visibilitychange", () =>
document.hidden ? video.pause() : video.play(),
);
2
3
# 4. Web Share
一键唤起系统分享面板,直达微信、微博、Telegram,需 HTTPS。
navigator.share?.({ title: "好文", url: location.href });
# 5. Wake Lock
锁定屏幕常亮,直播、PPT、阅读器不再自动息屏。
await navigator.wakeLock.request("screen");
# 6. Broadcast Channel
同域标签实时广播消息,登录态秒同步,告别 localStorage 轮询。
const bc = new BroadcastChannel("auth");
bc.onmessage = () => location.reload();
2
# 7. PerformanceObserver
无侵入采集 FCP、LCP、FID,一行代码完成前端性能监控。
new PerformanceObserver((list) =>
list.getEntries().forEach(sendMetric),
).observe({ type: "largest-contentful-paint", buffered: true });
2
3
# 8. requestIdleCallback
把埋点、日志丢进浏览器空闲时间,首帧零阻塞。
requestIdleCallback(() => sendBeacon("/log", data));
# 9. scheduler.postTask
原生优先级任务队列,低优任务后台跑,主线程丝滑。
scheduler.postTask(() => sendBeacon("/log", data), { priority: "background" });
# 10. AbortController
随时取消 fetch,路由切换不再旧请求竞态,兼容 100%。
const ac = new AbortController();
fetch(url, { signal: ac.signal });
ac.abort();
2
3
# 11. ReadableStream
分段读取响应流,边下载边渲染,大文件内存零爆涨。
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
appendChunk(value);
}
2
3
4
5
6
# 12. WritableStream
逐块写入磁盘或网络,实时保存草稿、上传大文件更稳。
const writer = stream.writable.getWriter();
await writer.write(chunk);
2
# 13. Background Fetch
PWA 后台静默下载,断网恢复继续,课程视频提前缓存。
await registration.backgroundFetch.fetch("video", ["/course.mp4"]);
# 14. File System Access
读写本地真实文件,需用户授权,Web IDE 即开即用。
const [fh] = await showOpenFilePicker();
editor.value = await (await fh.getFile()).text();
2
# 15. Clipboard
异步读写剪贴板,无需第三方库,HTTPS 环境安全复制。
await navigator.clipboard.writeText("邀请码 9527");
# 16. URLSearchParams
解析、修改、构造 URL 查询串,告别手写正则。
const p = new URLSearchParams(location.search);
p.set("page", 2);
history.replaceState({}, "", `?${p}`);
2
3
# 17. structuredClone
深拷贝对象、数组、Map、Date,循环引用也能完美复制。
const copy = structuredClone(state);
# 18. Intl.NumberFormat
千分位、货币、百分比一次格式化,国际化零配置。
new Intl.NumberFormat("zh-CN", { style: "currency", currency: "CNY" }).format(
1234567,
); // ¥1,234,567.00
2
3
# 19. EyeDropper
浏览器级吸管工具,像素级取色,设计系统直接调用。
const { sRGBHex } = await new EyeDropper().open();
# 20. WebCodecs
原生硬解码音视频,4K 60 帧流畅播放,CPU 占用直降。
const decoder = new VideoDecoder({
output: (frame) => ctx.drawImage(frame, 0, 0),
error: console.error,
});
decoder.configure({ codec: "vp09.00.10.08" });
2
3
4
5