将结构转为树结构
const linearStructure = [
{ id: 1, name: "总经理", parentId: null },
{ id: 2, name: "财务总监", parentId: 1 },
{ id: 3, name: "技术总监", parentId: 1 },
{ id: 4, name: "工程部副总", parentId: 3 },
{ id: 5, name: "软件开发部经理", parentId: 4 },
{ id: 6, name: "软件工程师", parentId: 5 },
{ id: 7, name: "质量保证部经理", parentId: 4 },
{ id: 8, name: "质量保证工程师", parentId: 7 },
{ id: 9, name: "销售总监", parentId: 3 },
{ id: 10, name: "销售经理", parentId: 9 },
{ id: 11, name: "销售团队", parentId: 10 },
];
//方法一 使用forEach结合filter
linearStructure.forEach((item) => {
item.children = linearStructure.filter((iten) => iten.parentId === item.id);
});
const rusult = linearStructure.filter((item) => !item.parentId);
console.log(rusult);
//方法二 使用Map结合forEach
function formatTree(arr){
const result = [];
const map = new Map();
arr.forEach(item=>map.set(item.id,{...item,children:[]}));
arr.forEach(item=>{
if(map.has(item.parentId)){
map.get(item.parentId).children.push(map.get(item.id))
}else{
result.push(map.get(item.id))
}
})
return result;
}
console.log(formatTree(linearStructure));
反转字符串
const str = "Hello World";
//方法一 转数组通过数组反转方法再转字符串
const newStr = str.split('').reverse().join('');
console.log(newStr);
//方法二 转数组然后通过reduce
const newStr2 = Array.from(str).reduce((acc,cur)=>`${cur}${acc}`,'');
console.log(newStr2);
实现柯里化函数add
function add(...args1){
let parms = args1;
function addFn(...args2){
parms = parms.concat(args2);
return addFn;
}
addFn.valueOf = ()=>{
return parms.reduce((acc,cur)=>{
return acc+cur;
},0)
}
return addFn;
}
console.log(add(1,2,3).valueOf()); //6
console.log(add(4)(5,6)(7,8,9).valueOf()); //39
虚拟列表
完善虚拟列表
<script setup>
import {computed, onMounted, reactive, ref} from "vue";
// 数据定义
const listRef = ref(null);
let scrollTop = ref(0);
let viewHeight = 0;
let itemHeight = 30;
let itemSum = ref(0);
let startIndex = ref(0);
// 后端返回的数据
const data = [];
for (let i = 1; i <= 200; i++) {
data.push({id: i, content: `列表${i}`});
}
// 计算属性
const handleListResult = computed(() => {
const endIndex = startIndex.value + itemSum.value;
endIndex > data.length ? data.length : endIndex;
const result = data.slice(startIndex.value, endIndex);
console.log(result);
console.log(startIndex.value, endIndex);
return result;
});
// 数据监听
// 生命周期钩子
onMounted(() => {
viewHeight = listRef.value.offsetHeight;
itemSum.value = Math.ceil(viewHeight / itemHeight);
});
// 方法处理
const handleListScroll = () => {
scrollTop.value = listRef.value.scrollTop;
startIndex.value = Math.floor(scrollTop.value / itemHeight);
};
const throttle = (fn, dalay) => {
let timer = null;
return function (...agrgs) {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, agrgs);
timer = null;
}, dalay);
};
};
const handleThrottleScroll = throttle(handleListScroll, 100);
</script>
<template>
<div class="list" @scroll="handleThrottleScroll" ref="listRef">
<div :style="{height: `${itemHeight * data.length}px`,}">
<ul
:style="{
transform: `translateY(${startIndex * itemHeight}px)`,
}"
>
<li class="list_item" v-for="item in handleListResult" :key="item.id">
{{ item.content }}
</li>
</ul>
</div>
</div>
</template>
<style scoped lang="less">
.list {
width: 310px;
height: 320px;
border: 1px solid red;
overflow-y: scroll;
.list_item {
height: 30px;
width: 300px;
border: 1px solid green;
margin-left: -10px;
list-style: none;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
下拉加载更多
<script setup>
import {computed, ref} from "vue";
const page = ref(1);
const pageSize = 10;
const pageItem = 30;
const dataRef = ref(null);
const data=[];
for (let i= 1; i < 200; i++){
data.push({id:i,content:'数据'+i})
}
const dataResult = computed(()=>{
return data.slice(0,page.value*pageSize);
})
const handleScroll = () => {
const scrollTop = dataRef.value.scrollTop;
const boxHeight = dataRef.value.offsetHeight;
console.log(scrollTop,boxHeight)
if(scrollTop >= pageItem*pageSize*page.value - boxHeight + 10){
page.value++;
console.log('加载更多数据');
}
}
</script>
<template>
<div class="bigbox" @scroll="handleScroll" ref="dataRef">
<div :style="{height: `${dataResult.length*pageItem+22}px`}">
<div class="data_item" v-for="item in dataResult">{{item.content}}</div>
</div>
</div>
</template>
<style scoped>
.bigbox {
width: 320px;
height: 320px;
border: 1px solid red;
overflow-y: scroll;
.data_item {
width: 300px;
height: 30px;
border: 1px solid green;
list-style: none;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
简易版axios实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(config.method || "GET", config.url);
// 判断是否有请求头
if (Reflect.ownKeys(config.headers||{}).length > 0) {
Object.keys(config.headers).forEach((key) => {
xhr.setRequestHeader(key, config.headers[key]);
});
}
xhr.onload = () => {
resolve({
data: xhr.responseText,
status: xhr.status,
});
};
xhr.onerror = () => {
reject("Error");
};
xhr.send();
});
}
(async () => {
try {
const result = await myAxios({
url: "https://jsonplaceholder.typicode.com/todos/1",
});
console.log(result.status);
} catch (error) {
console.log("error",error);
}
})();
</script>
</body>
</html>
实现一个获取时间的函数 YYYY-MM-DD HH-mm-ss (装饰者模式)
function addZero(str) {
return str.toString().padStart(2, "0");
}
function getTime(currentTime) {
const year = currentTime.getFullYear();
const month = addZero(currentTime.getMonth() + 1);
const day = addZero(currentTime.getDate());
const hour = addZero(currentTime.getHours());
const minute = addZero(currentTime.getMinutes());
const second = addZero(currentTime.getSeconds());
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
console.log(getTime(Date()));
两数之和
// 给定一个数组,给定一个计算结果target,查找出来符合条件的数据索引
function findSum1(arr, target) {
for (let i = 0; i < arr.length; i++) {
const findIndex = arr.findIndex((item) => item === target - arr[i]);
if (findIndex !== -1) {
return [i, findIndex];
}
}
return [];
}
function findSum2(arr, target) {
const map = new Map();
arr.forEach((element) => {
map.set(arr[element], element);
});
for (let i = 0; i < arr.length; i++) {
const findValue = target - arr[i];
if (map.has(findValue)) {
return [i, map.get(findValue)];
}
}
return [];
}
console.log(findSum1([8, 2, 6, 5, 4, 1, 3], 7));
console.log(findSum2([8, 2, 6, 5, 4, 1, 3], 7));
找出出现两次的数字
function findValue(arr) {
return arr.filter((item, index) => arr.indexOf(item) !== index);
}
function findValue2(arr) {
const newSet = new Set();
const result = [];
for (let item of arr) {
if (newSet.has(item)) {
result.push(item);
} else {
newSet.add(item);
}
}
return result;
}
console.log(findValue([1, 2, 2, 3, 4, 5, 6, 7, 8]));
console.log(findValue2([1, 2, 2, 3, 4, 5, 6, 7, 8]));
判断字符串是否有效
const map = new Map();
map.set("(", ")");
map.set(")", "(");
map.set("{", "}");
map.set("}", "{");
map.set("[", "]");
map.set("]", "[");
function isValid(str) {
return str.split("").every((item) => str.includes(map.get(item)));
}
console.log(isValid("[]")); //true
console.log(isValid("()")); //true
console.log(isValid("{[()]}")); //true
console.log(isValid("(")); //false
console.log(isValid("{(]}")); //false
实现debounce函数
function debounce(fn, delay, immediate = false) {
let time = null;
return function (...args) {
if (immediate && !time) {
fn.apply(this, args);
}
if (time) clearTimeout(time);
time = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
找到第一个不重复出现的字符的下标
function findIndex(str) {
const map = new Map();
for (let item of str) {
if (map.has(item)) {
map.set(item, map.get(item) + 1);
} else {
map.set(item, 1);
}
}
for (let i = 0; i < str.length; i++) {
if (map.get(str[i]) === 1) {
return i;
}
}
return -1;
}
console.log(findIndex("abcabcde"));
深拷贝实现
// 深拷贝实现
function deepClone(obj) {
if (!(obj instanceof Object)) {
throw new TypeError("请传入复杂数据类型");
}
return Object.keys(obj).reduce((acc, cur) => {
// 如果值是数组
if (Object.prototype.toString.call(obj[cur]) === "[object Array]") {
acc[cur] = [...obj[cur]];
} else if (typeof obj[cur] === "object" && obj[cur] !== null) {
// 如果值是对象
acc[cur] = deepClone(obj[cur]);
} else {
// 属性值为基本数据类型
acc[cur] = obj[cur];
}
return acc;
}, {});
}
const obj1 = { a: 1, b: { c: 2 }, d: [99, 98] };
const obj2 = deepClone(obj1);
obj1.b.c = 5;
obj1.d = [90, 91, 92];
console.log(obj2);
flat实现
Array.prototype.myFlag = function (deep) {
let step = arguments.length === 1 ? deep : 1;
let result = [];
for (let i = 0; i < this.length; i++) {
if (Array.isArray(this[i]) && step > 0) {
result = result.concat(this[i].myFlag(step - 1));
} else {
result.push(this[i]);
}
}
return result;
};
console.log([1, 2, [3, 4, [5]]].myFlag(2));