一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
一、grid
的使用
1、grid
跟flex
的比较
grid
可以看作是二维的布局,flex
是一维的布局
2、grid
的属性
grid-template-columns
和grid-template-rows
: 定义行列的宽度,宽高的设置可使用px
/%
/repeat()
/auto-fill
关键字/fr
关键字/minmax()
函数/auto
关键字,使用案例有:
// 表示每列宽度100px,每行有3列
div{
display: grid;
grid-template-columns: 100px 100px 100px;
}
// 表示每行有4列,列宽度为20% 30% 20% 30%
div{
display: grid;
grid-template-columns: repeat(2, 20% 30%);
}
// 表示列宽100px,每行自动填充,填充不下换行
div{
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
}
// 表示每行自动填充,填充不下换行,列宽度为100px 100px 200px …………
div{
display: grid;
grid-template-columns: repeat(auto-fill, 100px, 1fr, 2fr);
}
// 表示每行有两列,列宽为50%,且每列宽度不小于100px
div{
display: grid;
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
}
// 表示每行有3列,列宽为100px 100px auto,第三列有浏览器自己决定长度
div{
display: grid;
grid-template-columns: 100px 1fr auto;
}
grid-row-gap
、grid-column-gap
和grid-gap
属性:设置行/列间距
// 表示行间距=列间距=20px
div {
grid-gap: 20px; // grid-gap: <grid-row-gap> <grid-column-gap>,第二个值可省略
}
-
grid-template-areas
属性:用于定义区域,网格线的命名会自动变成区域名-start
,区域名-end
-
grid-auto-flow
属性:与flex-direction
类似,设置子元素的排序顺序,值为row
/column
/row-dense
/column-dense
-
row
/column
: 表示按行/列排布,排不下的换行/列排布 -
row-dense
/column-dense
: 表示按行/列紧凑排布,当下一个排不下时会去找下一个能排下的元素,直至换行/列
- 单元格内布局
取值:
center
、start
、end
和stretch
(拉伸,默认值)
justify-items
: 单元格内的水平位置;align-items
: 单元格内的垂直位置;place-items: <align-items> <justify-items>
- 整个内容区域布局
取值有
center
、start
、end
、stretch
、space-around
、space-between
和space-evenly
justify-content
: 整个内容区域在容器中的水平位置;align-content
: 垂直位置;place-content: <align-content> <justify-content>
7.常用的有以上,其余的…………………………好多属性,再写也记不住了~ 用到的时候再记吧。
二、history
和 hash
的区别
这两种都可以实现客户端改变视图的同时,不向后端发出请求。
1、hash
模式
- 通过在
URL
锚点#
后面拼接路由参数的方法,这种改变hash
的方法不会引起浏览器重新加载页面 - 利用
window.onhashchange
事件,监听hash
的更改,从而加载对应的页面(window.location.hash.substr(1)
)
2、history
模式
- 利用
H5
History Interface
中新增的pushState()
和replaceState()
方法,来记录历史路由栈 - 该模式下,一般刷新之后会报
404
错误,需要后端ng
的配置 pushState
和replaceState
方法,只能导致history
对象变化,浏览器不会向后端发送请求,也不会触发popstate
事件(popstate
事件是在点击浏览器前进后退按钮之后触发执行的)history
模式下的路由监听使用popstate
事件来实现
三、Map
数据结构和WeakMap
数据结构
1、Map
Map
结构是一种数组键值对格式,它跟对象明显不一样的点是,它不对值进行强制类型转换Map
方法let map = new Map()
: 实例化一个Map
数据结构set()
:map.set('name', 'test')
get()
:map.get('name')
delete()
:map.delete('name')
clear()
:map.clear()
size
:map.size // 获取长度
- 遍历:
map.forEach((value, key, self) => {})
- Map转对象,通过
Object.fromEntries(map)
方法
2、WeakMap
WeakMap
方法:没有了Map
的遍历、clear
清除、获取长度size
的方法,只保留了以下四个delete()
set()
get()
has()
- 同
Map
不同的一点,WeakMap
只接受对象作为键值 WeakMap
是弱引用(对对象的弱引用是指当该对象应该被GC
(Garbage Collection
垃圾回收机制)回收时不会阻止GC
的回收行为):当外部的引用被删除后,WeakMap
内部的引用会相应的被GC
垃圾回收WeakMap
的使用场景: 可用于写DOM节点
的监听事件,当DOM
节点被删除后,WeakMap
中对于该DOM
节点的引用也会被垃圾回收,不容易造成内存泄漏
四、Set
和WeakSet
Set
和WeakSet
的区别同Map
和WeakMap
类似
1、Set
:本身是一个构造函数,类似于数组,但是数组中的值是唯一、不重复的
Set
方法add()
delete()
has()
clear()
size
keys()
: 键名的遍历器values()
: 键值的遍历器entries()
: 键值对的遍历器forEach()
: 使用回调函数遍历每个成员
- 常用的使用场景:用于对数组的去重
let a = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,8,9,10,10,11];
let b = [2,3,4,5,3,2,1,32,2321,12121];
let set = new Set([...a, ...b])
// 输出set结果:Set(14) {1, 2, 3, 4, 5, …}
let array = Array.from(set)
// 输出array结果:(14) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 32, 2321, 12121]
2、WeakSet
WeakSet
: 结构同Set
类似,区别是其成员只能是对象,且为Set
和WeakSet
,成员随时会消失,因此不支持遍历
WeakSet
方法,去除掉遍历方法以及size
,只有以下3个方法add()
delete()
has()
WeakSet
常用的使用场景:用于存储DOM
节点,当节点被移除后,相应的WeakSet
也会被垃圾回收,不容易造成内存泄漏
五、移动端布局
移动端布局下,meta
标签的常用写法
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
移动端的布局方法,常见的有以下几种:
1、rem
布局
rem
同 em
的区别是:rem
是相对根元素font-size
来布局,而em
是相对父元素
设计思路:
-
移动端屏幕尺寸规定为
750px
,设计稿尺寸为750px
-
若将屏幕宽度分出为
10
份,每一份大小为750/10 = 75
-
html
根元素font-size: 设备宽度/75 + 'px'
,handleFontSizeRoot() { let width = document.documentElement.offsetWidth / 75; document.documentElement.style.fontSize = width + 'px'; }
-
css
布局时写法上:750px === 75rem
,100px === 10rem
,12px === 1.2rem
-
postcss
:一种对css
编译的工具,类似babel-loader
,可安装postcss-pxtorem
插件,将px
转换成rem
,该插件对于px
的检测是区分大小写的(即,Px
/PX
/pX
不会被转换成rem
);(这个
loader
先简单提下,后面会有说明,具体可看下postcss
对scoped
的转译)
2、@media
媒体查询
@media
媒体类型查询,媒体类型取值有以下4个
all
所有设备print
打印设备screen
电脑屏幕、平板屏幕、移动端屏幕speech
@media
关键字查询,常用关键字有以下几种:
max-width: 1000px
查询匹配宽度小于1000pxmin-width: 750px
查询撇皮=宽度大于750pxand
与运算连接符only
表示唯一not
否运算连接符
@media
可以用在link
标签上,用于按需加载css
资源<link rel="stylesheet" href="css/1.css" media="(max-width:750px)"/>
3、百分比
- 直接使用百分比来布局,该方法下图片布局比较混乱
4、vh
和vw
布局方法
- 使用过程中有问题:
IOS
下,软键盘是叠在可视窗口上的- 安卓下,软键盘会撑开一定高度
六、postcss
对scoped
的转译
七、文档流
1、会脱离文档流的布局方式
float
浮动absolute
布局方式fixed
布局方式: 主要用于贴靠浮动
2、清除浮动的方法
- 父元素设置宽高自动撑起
- 浮动元素下新增一个空的同级元素,设置清除浮动样式:
clear: both
- 浮动元素的父元素设置伪类
::after
::before
从而清除浮动
八、width
offsetWidth
clientWidth
scrollWidth
innerWidth
的区别
width
: 可读写,通过style.width
来修改之,返回带单位的字符串offsetWidth
:只读属性,返回整数值,表示元素的实际宽度,offsetWidth = width + padding + border
clientWidth
: 可视区域的宽度scrollWidth
:实际内容的宽度innerWidth
:window.innerWidth
表示浏览器窗口的内部宽度
九、height
offsetHeight
clientHeight
scrollHeight
innerHeight
的区别
同上一点类似
十、for of
跟 for in
遍历器的区别
1、for of
for(let i of arr)
i
为键值value
- 可用于遍历字符串,遍历得到字符
- 无法直接遍历对象拿到键值,但可以通过
Object.values
Object.keys
Object.entries
来实现遍历
2、for in
for(let i in arr)
i
为键名key
- 可用于遍历字符串,遍历得到字符的索引值
- 可用于遍历对象,遍历得到对象的
key
十一、重绘和回流
回流一定会触发重绘,重绘不一定会触发回流;
回流的代价会高于重绘。
1、回流
引起场景:当有元素宽高、布局、显示或隐藏,或元素内部的文字结构发生变化时,会引起回流(重新构建页面)
- 添加、删除DOM元素
DOM
元素发生位移DOM
元素尺寸变化(包括border
padding
width
height
等DOM
元素文本更改- 页面一开始渲染的时候
- 页面尺寸改变
JS
中获取DOM
的偏移量属性,如offsetWidth
clientWidth
(相关原因后面有写)
2、重绘
当元素宽高、布局、显影等都未有更改,只是改变了元素的外观风格时,会引起重绘
DOM
元素样式更改(visibility
、color
、background-color
等)input
数据框的变化css
伪类
3、优化重绘和回流
- 用
transform
替换top
、left
、margin-top
、margin-left
这些位移属性 opacity
和visibility
visibility
会引起重绘但不会引起回流- 只用
opacity
会引起回流 opacity
与transform: translateZ/3d
不会产生回流和重绘
- 不要用
js
对dom
元素设置样式等,直接用一个className
- 避免频繁用
js
获取dom
的样式,如offsetWidth
,clientWidth
这些。浏览器有一个回流的缓冲机制,多个回流会保存在一个栈里面,当这个栈满了浏览器会一次性触发所有样式的更改切刷新这个栈。当获取dom
的样式时,浏览器为了给到一个准确的答案会不停刷新这个缓冲栈,导致页面回流增加。 - 动画的速度按照业务需求定,必要时可以开启
GPU
加速 - 给需要频繁重绘和回流的节点单独设置图层,可设置成
absolute
、fixed
等 - 避免频繁操作
DOM
,可通过cloneNode
赋值DOM
节点出来,更改完成后再replaceChild
4、16ms
优化
大多数设备的刷新频率是60次/s,即没渲染一次要在1000ms/60次=16.6ms内完成,超出这个时间,页面的渲染会出现卡顿现象,影响用户体验
浏览器渲染页面的过程大致如下::
- 解析
HTML
,生成DOM
树 - 解析
CSS
,生成CSSOM
树 - 将
DOM
树和CSSOM
树结合,生成Render
渲染树 Layout
(回流)布局,根据窜蚺属,确定DOM
元素在屏幕上显示的大小和位置Paint
(重绘) 绘制DOM
元素文字、颜色、图像、边框和阴影等Composite
渲染层合并,按照合理的顺序合并图层然后显示到屏幕上
十二、关于线上环境bug的及时跟进
**sentry
错误日志监控**: 主要用于vue
项目发生产之后的bug
收集;
目前开发的时候我们可调试,但一旦发生产之后,若出现bug
,开发人员没办法及时获取到bug
复现场景,只能依靠用户的反馈,这点很不友好,所以引入sentry
错误日志监控,至于搭建流程,具体可看下官网(外国网站,国内浏览很慢~需要VPN
)
十三、防抖和节流
1、防抖:
- 原理:事件触发后,延迟
n
秒再执行,n
秒内重复触发,则重新设置定时器计时 - 实现方法:
- 触发事件,清除定时器
- 设置定时器
n
秒后执行
- 应用场景:
input
框边输入边调用接口搜索
2、节流:
- 原理:某个时间段内只触发一次事件(即使多次点击)
- 实现方法:
- 判断
flag
为true
时,进入事件 - 事件中 置
flag
为false
, 设置定时器 - 定时器执行完成后,置
flag
为true
- 应用场景:
button
多次触发- 懒加载监听滚动条位置
十四、Promise的异常捕获如何实现
先不做说明,这个关于Promise
的实现原理,下次补上
十五、webpack打包的步骤
具体可看下这两篇:
十六、webpack import原理
还在了解中,后面补充进来
十七、Vue3
新出的composition API
跟 原本的option API
有什么区别
首先,这两个的使用是不冲突的,需要使用哪个可供开发者自由选择。
十八、setTimeout跟Promise的执行顺序
这个问题是关于浏览器 JS引擎线程的事件循环机制,具体可看下我之前的文章