经典Flex布局 ❤️
如今 Flex布局 不管是移动端还是PC端的应用已经非常广泛了,下面我列举几个平时项目中非常常见的几个需求。以下例子我们都以Vue项目和js为例~
flex布局均匀分布后换行问题
需求一:ul下有多个li,每三个li排一列,多余的换行显示。
很显然,绝大部分的小伙伴都会使用Flex布局,很显然会出现一个问题就是如果li是3的倍数的话就能正常显示,若不是的话,布局就不是产品经理满意的结果。
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
解决方案:
我们在ul的底部新增li,个数为数组总长度%3的余数即可。
vue
<li class="item" style="border: none;" v-for="(ite, idx) in (3-list.length%3)==3?0:(3-list.length%3)" :key="idx"></li>
js
<ul id="ul">
</ul>
<script>
var ul = document.getElementById('ul');
for(let i =0;i<8;i++){
var li = document.createElement('li');
li.innerText=i;
ul.appendChild(li);
}
for(let i=0;i< ((3-8%3)==3?0:(3-8%3)) ;i++){
var li = document.createElement('li');
li.style.border = "none";
ul.appendChild(li);
}
</script>
<style>
ul,li{
list-style: none;
}
ul{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
li{
width:30%;
height: 100px;
border: 1px solid black;
margin: 20px 0;
align-items: center;
}
</style>
统计网页中出现的标签 去重
实现步骤:
- 获取所有的DOM节点
- NodeList集合转化为数组
- 获取数组每个元素的标签名
- 去重
new Set([...document.querySelectorAll('*')].map(ele=>ele.tagName)).size
防抖和节流
如今前端界面效果越来越复杂,有一些频繁操作会导致页面性能和用户体验度低。像:输入框搜索会频繁调端口接口、放大缩小窗口等。
防抖 - debounce 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
const debounce = (fn, delay) => {
let timer = null;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
节流 - throttle 当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
const throttle = (fn, delay = 500) => {
let flag = true;
return (...args) => {
if (!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay);
};
};
Jsonp的原理
原理:
首先在客户端注册一个callback,然后把callback的名字传给服务器。此时,服务器先生成json数据,然后以javascript语法的方式,生成function,function名字就是传递上来I带参数jsonp。最后将json数据直接以入参的方式,放置function中,这样就生成js语法的文档,返回给客户端。客户端浏览器,解析script变迁,并执行返回javascript文档,此时数据作为参数,传入了客户端预先定义好的callback函数里。简单的说,就是利用script标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。
function jsonp({url, params, cb}) {
return new Promise((resolve, reject) => {
window[cb] = function (data) { // 声明全局变量
resolve(data)
document.body.removeChild(script)
}
params = {...params, cb}
let arrs = []
for(let key in params) {
arrs.push(`${key}=${params[key]}`)
}
let script = document.createElement('script')
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
jsonp的缺点:
- 只能发送Get请求 不支持post put delete
- 不安全 xss攻击
new的原理
简单来说,四步:
1、在函数内部自动创建一个对象
2、修改函数的作用域,将this指向该对象
3、为该对象添加属性和方法
4、返回该对象
function _new () {
var obj = new Object();
var [func, ...args] = [...arguments];
obj.__proto__ = func.prototype;
var result = func.call(obj,...args);
if(result && ( typeof(result) === 'object' || typeof(result) === 'Function')){
return result;
}
return obj;
}
function Animal(name,age){
this.name = name;
this.age = age;
}
//通过new创建构造实例
let dog1 = new Animal('dog1',2);
console.log(dog1.name) // dog1
console.log(dog1.age)//2
//通过_new方法创造实例
let dog2 = _new(Animal,'dog2',3);
console.log(dog2.name)//dog2
console.log(dog2.age) //3
去重❤️
let arr2 = [1, 2, 3, 2, 33, 55, 66, 3, 55];
第一种:
let newArr = [];
arr2.forEach(item => {
if(newArr.indexOf(item) == '-1') {
newArr.push(item);
}
})
console.log(newArr);
// (6) [1, 2, 3, 33, 55, 66]
第二种: 推荐
let newArr = [...new Set(arr2)];
console.log(newArr);
// (6) [1, 2, 3, 33, 55, 66]
第三种:
Array.from方法可将Set结果转为数组
所以 还可以
let newArr = Array.from(new Set(arr2));
console.log(newArr);
// (6) [1, 2, 3, 33, 55, 66]
合并 ❤️
let arr3 = ['a', 'b']
let arr4 = ['c', 'd']
方法一:ES5
let arr5 = arr3.concat(arr4);
console.log(arr5);
// ['a', 'b', 'c', 'd']
方法二:ES6
let arr6 = [...arr3, ...arr4];
console.log(arr6);
// ['a', 'b', 'c', 'd']
展平❤️
let arr7 = [1, 2, [3, 4], [5, 6, [7, 8, 9]]];
第一种: flat
let arrNew = arr7.flat(Infinity);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
第二种:
let arrNew = arr7.join().split(',').map(Number);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
第三种:
let arrNew = arr7.toString().split(',').map(Number);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
第四种:
const flattern = (arr) => {
const result = []
arr.forEach((item) => {
if (Array.isArray(item)) {
result.push(...flattern(item))
} else {
result.push(item)
}
})
return result
}
flattern(arr7);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
第五种:
function flatten(arr) {
return [].concat(
...arr.map(x => Array.isArray(x) ? flatten(x) : x)
)
}
flattern(arr7);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
冒泡排序❤️
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
冒泡排序算法的原理如下:
1、 比较两个相邻的元素,若前一个比后一个大,则交换位置
2、 第一轮的时候最后一个元素应该是最大的一个
3、 对所有的元素重复以上的步骤,除了最后一个
function bubbleSort(arr) {
for(let i=0; i<arr.length; i++) {
for(let j=0; j<arr.length - i - 1; j++) {
if(arr[j+1] < arr[j]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));
// [ 1, 3, 6, 7, 12, 44, 77, 99 ]
注意:最后一个元素不用比较。
快速排序 ❤️
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
快速排序算法的原理如下:
1、 找基准(一般是以中间项为基准)
2、 遍历数组,小于基准的放在left,大于基准的放在right
3、递归
function quickSort(arr) {
if(arr.length <= 1) return arr;
let mid = Math.floor(arr.length / 2);
let midItem = arr.splice(mid, 1)[0];
let leftArr = [];
let rightArr = [];
for(let i=0; i<arr.length; i++) {
let current = arr[i];
if(current >= midItem) {
rightArr.push(current);
} else {
leftArr.push(current);
}
}
return quickSort(leftArr).concat([midItem], quickSort(rightArr));
}
console.log(quickSort(arr));
// [ 1, 3, 6, 7, 12, 44, 77, 99 ]
最后
一起学习前端,共同进步!❤️❤️❤️❤️❤️❤️
文章参考:https://juejin.im/post/5e8153bf6fb9a03c840d509d#heading-25