前言

总结一下个人开发总封装的实用方法,以便后期开发方便

方法

合并表格行

在开发表格过程中,总是需要合并单元格子,后端会把相同的数据放在一起,前端处理合并,以下是利用哈希值处理的合并方法。

1
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
//tableData 合并的表格数据,matchKey为匹配的key数组,可匹配多个
function dealWithMergeData(tableData, matchKey) {
let spanObject = {}
//遍历匹配项
matchKey.forEach((spanKeyItem) => {
if (!spanObject[spanKeyItem]) spanObject[spanKeyItem] = [];
//起始索引
let startIndex = 0;
//遍历表格数据
for (let i = 0; i < tableData.length; i++) {
let tableItem = tableData[i];
if (i != 0) {
//如果当前的值和上一个一样
if (tableItem[spanKeyItem] === tableData[i - 1][spanKeyItem]) {
//起始自增
spanObject[spanKeyItem][startIndex].rowspan++;
//自身设置为空
spanObject[spanKeyItem][i] = {
rowspan: 0,
colspan: 0
}
} else {
//如果不等于,那么自身就是起始索引,重新开始
startIndex = i;
spanObject[spanKeyItem][startIndex] = {
rowspan: 1,
colspan: 1
}
}
} else {
spanObject[spanKeyItem][i] = {
rowspan: 1,
colspan: 1
}
}
}
})
return spanObject
}

//dealWithMergeData(tableData,['key','vehicleId'])

reduce 进行数据结构的转换

1
2
3
4
5
6
7
8
9
10
11
12
const arr = [
{ id: "1", name: "张三", age: 11 },
{ id: "1", name: "李四", age: 12 },
{ id: "2", name: "王五", age: 13 },
{ id: "3", name: "赵六", age: 14 },
{ id: "2", name: "孔七", age: 15 }
];

function groupArrayByKey(arr = [], key) {
return arr.reduce((t, v) => (!t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t), {})
}
groupArrayByKey(arr, "id");

动态加载 JS 文件

在一些特殊的场景下,特别是一些库和框架的开发中,我们有时会去动态的加载 JS 文件并执行,下面是利用 Promise 进行了简单的封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function loadJS(files, done) {
// 获取head标签
const head = document.getElementsByTagName('head')[0];
Promise.all(files.map(file => {
return new Promise(resolve => {
// 创建script标签并添加到head
const s = document.createElement('script');
s.type = "text/javascript";
s.async = true;
s.src = file;
// 监听load事件,如果加载完成则resolve
s.addEventListener('load', (e) => resolve(), false);
head.appendChild(s);
});
})).then(done); // 所有均完成,执行用户的回调事件
}

loadJS(["test1.js", "test2.js"], () => {
// 用户的回调逻辑
});

利用闭包实现函数只执行一次

1
2
3
4
5
6
7
8
9
10
export function once (fn) {
// 利用闭包判断函数是否执行过
let called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
}

实现curring

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function add(a, b, c) {
return a + b + c;
}
function currying(fn, ...args) {
function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args)
} else {
return function (...arg2) {
return curried.apply(this, args.concat(arg2));
}
}
}
return curried.apply(this, args)
}
const a1 = currying(add, 1,2,3);//6
const a2 = currying(add)(1)(2)(3);、、6

递归获取对象属性

如果让我挑选一个用的最广泛的设计模式,我会选观察者模式,如果让我挑一个我所遇到的最多的算法思维,那肯定是递归,递归通过将原始问题分割为结构相同的子问题,然后依次解决这些子问题,组合子问题的结果最终获得原问题的答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const user = {
info: {
name: "张三",
address: { home: "Shaanxi", company: "Xian" },
},
};

// obj是获取属性的对象,path是路径,fallback是默认值
function get(obj, path, fallback) {
const parts = path.split(".");
const key = parts.shift();
if (typeof obj[key] !== "undefined") {
return parts.length > 0 ?
get(obj[key], parts.join("."), fallback) :
obj[key];
}
// 如果没有找到key返回fallback
return fallback;
}

console.log(get(user, "info.name")); // 张三
console.log(get(user, "info.address.home")); // Shaanxi
console.log(get(user, "info.address.company")); // Xian
console.log(get(user, "info.address.abc", "fallback")); // fallback

大屏前端自适应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//公共方法
/* 根据浏览器大小推断缩放比例 */
export const getScale = (w: number, h: number) => {
const ww = window.innerWidth / w;
const wh = window.innerHeight / h;
return ww < wh ? ww : wh;
};

/* 浏览器监听 resize 事件 */
export const screeResize = (el: HTMLDivElement, W: number, H: number) => {
if (el) {
el.style.width = `${W}px`;
el.style.height = `${H}px`;
el.style.transform = `scale(${getScale(W, H)}) translate(-50% ,-50%)`;
}
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//应用
import { debounce } from "lodash";
import { screeResize } from "@/utils";
/* @description:大屏自适应模块*/
const dataScreenRef = ref<HTMLDivElement | null>(null);
const onResize = () => {
screeResize(dataScreenRef.value as HTMLDivElement, 1920, 1080);
};

onMounted(()=>{
if (dataScreenRef.value) {
onResize();
window.addEventListener("resize", debounce(onResize, 150));
}
1
2
3
4
5
6
7
8
9
10
//大屏容器样式
.screenContainer{
transform-origin: left top;
position: fixed;
width: 1920px;
height: 1080px;
top: 50%;
left: 50%;
user-select: none;
}