# 前端爱好者学习周刊:第5期
2019-12-07
htmlcssjs
# 【html+css】
# 1. display:inline-block
的问题
剖析一些经典的CSS布局问题,为前端开发+面试保驾护航 (opens new window)
<div class="one">
<div class="box1"></div>
<div class="box2"></div>
</div>
2
3
4
.box1{
width:100px;
height:100px;
display: inline-block;
background:red;
}
.box2{
width:100px;
height:100px;
display: inline-block;
background:blueviolet;
}
2
3
4
5
6
7
8
9
10
11
12
如图所示元素被当成行内元素排版的时候,元素之间的空白符(空格、回车换行等)都会被浏览器处理,根据CSS中white-space
属性的处理方式(默认是normal,合并多余空白),原来HTML代码中的回车换行被转成一个空白符,在字体不为0的情况下,空白符占据一定宽度,所以inline-block
的元素之间就出现了空隙。
解决办法:
- 1.把第一个
div
结尾和第二个div
开头放在一行:
<div class="one">
<div class="box1"></div><div class="box2"></div>
</div>
2
3
- 2.父元素中设置
font-size: 0
,在子元素上重置正确的font-size
.one{
font-size:0;
}
.box1,.box2{
font-size:14px;
}
2
3
4
5
6
- 3.为子元素设置
float:left
.box1,.box2{
float:left;
}
2
3
# 2.布局题,高始终为宽的一半
剖析一些经典的CSS布局问题,为前端开发+面试保驾护航 (opens new window)
<body>
<div class="box">
<div class="text">A</div>
</div>
</body>
2
3
4
5
- 第一种:vw
*{
padding:0;
margin:0;
}
.box{
width:calc(100vw - 20px);
height:calc(50vw - 10px);
background:pink;
margin:0 auto;
display:flex;
justify-content:center;
align-items:center;
}
2
3
4
5
6
7
8
9
10
11
12
13
- 第二种
height:0;padding-bottom:50%;
*{
padding:0;
margin:0;
}
body{
padding:0 10px;
}
.box{
position: relative;
width: 100%;
height: 0;
padding-bottom: 50%;
background:pink;
margin:0 auto;
}
.text{
position:absolute;
bottom:50%;
left:50%;
transform: translate(-50%,-50%);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 第三种:如果你使用了rem的话:
*{
padding:0;
margin:0;
}
body{
font-size:14px;
}
.box{
position: relative;
width: calc(1rem - 20px);
height: calc(0.5rem - 10px);
background: pink;
margin:0 auto;
display: flex;
justify-content:center;
align-items:center;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
document.documentElement.style.fontSize = window.innerWidth + 'px'
window.addEventListener('resize',function(){
document.documentElement.style.fontSize = window.innerWidth + 'px'
})
2
3
4
5
documentElement 属性以一个元素对象返回一个文档的文档元素。
HTML 文档返回对象为HTML元素 注意: 如果 HTML 元素缺失,返回值为 null。
# 4.flex-start布局最后一个在end处的小技巧
<div class="box">
<button>1121</button>
<button>1121</button>
<button>1121</button>
<button>right</button>
</div>
2
3
4
5
6
.box{
width:100%;
display: flex;
justify-content:flex-start;
align-items:center;
}
button{
width:100px;
height:35px;
}
button:last-child{
margin-left:auto;
}
2
3
4
5
6
7
8
9
10
11
12
13
# 【JavaScript】
# 1.['1', '2', '3'].map(parseInt)
['1', '2', '3'].map((item, index) => {
return parseInt(item, index)
})
2
3
值为[1,NaN,NaN]
parseInt('2', 1)
为NaN的原因——————1进制的最大值为1,但此为2,所以为NaN;parseInt('3', 2)
同理
# 2. const和let在全局作用域中定义的变量并不是window的属性
# 3.防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
每次触发事件时都取消之前的延时调用方法
// 防抖
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 500);
};
}
2
3
4
5
6
7
8
9
10
# 4.节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
每次触发事件时都判断当前是否有等待执行的延时函数
// 节流
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500);
};
}
2
3
4
5
6
7
8
9
10
11
12
13
# 5. recast
(待学习)JS底层知识:AST抽象语法树 (opens new window)
# 6.call 和 apply 的区别
**apply()和 call()的作用:**给函数传参、扩充作用域
两者区别在参数传递格式:
- 1.第一个参数都是,指定函数体内this的指向
- 第二个参数开始不同,apply是传入带下标的集合,数组或者类数组,apply把它传给函数作为参数,call从第二个开始传入的参数是不固定的,都会传给函数作为参数
**性能:**call比apply的性能要好,平常可以多用call, call传入参数的格式正是内部所需要的格式
es6 引入了 Spread operator (延展操作符) 后,即使参数是数组,可以使用 call
let params = [1,2,3,4]
xx.call(obj, ...params)
2
# 7.ES6的模块化---defaut export 和 named export
对于 ES6 模块来说,会有 defaut export 和 named export 的区别。有些开发者喜欢把所有东西都弄成一个对象塞到 default 里面。Default export 在概念上来说并不仅仅一个名字叫做 default 的 export,虽然它会被这样转译。把一切东西都塞到 default 里面是一个错误的选择,会让 tree-shaking 无效。从语意上来说,default export 用来说明这个模块是什么,named export 用来说明这个模块有什么。合理的模块拆分是一定可以让编译器只打包到所需的代码的。
上面这段话来自于这篇文章中---浅谈 ES 模块和 Webpack Tree-shaking (opens new window);我觉得作者这句话写的很棒。摘抄。
# 8. Webpack Tree-shaking
浅谈 ES 模块和 Webpack Tree-shaking (opens new window)
依然是这篇文章。
当代码中存在并没有使用的函数或者变量之类的,并不止于vscode就可以分辨出来的那个变量没有使用这样的级别,而是比如一个变量在从a引到b,从b引到c,一直引,最终发现其实这个变量根本就没有使用到。或者一个文件暴漏了一个模块,但是在整个系统中,只引用了a模块,b从未被使用等这些情况下,webpack打包的过程中就会打包上,造成冗余,增加每一次网络传输的耗时;
插件webpack-deep-scope-analysis-plugin (opens new window)
插件本身的原理:作用域分析
所谓作用域分析,就是可以分析出代码里面变量所属的作用域以及他们之间的引用关系。有了这些信息,就可以推导出导出变量和导入变量之间的引用关系
插件的实现基础:ES6的模块化特点
这个之所以能够实现,靠的是 ES6 优秀的模块设计 ?。CommonJS 的设计过于灵活,对静态分析不友好。ES6 module 则有诸多限制:比如说只能在文件的顶部 import(CommonJS 的 require 语法允许在文件的任意位置调用),export { ... } 语法保证了导出的变量不会是 getter/setter 之类奇怪的东西(这个 block 不是一个 Object),变量也不能被重新绑定。以上种种设计可以让分析器一定程度上判断出导入和导出变量的关系,让这个插件的实现成为了可能。