实现三列布局的方法
第一种:可以使用浮动+margin
第二种:浮动+BFC
<!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>
<div class="box">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
</body>
</html>
<style>
.left {
float: left;
width: 200px;
height: 200px;
background: red;
}
.right {
float: right;
width: 200px;
height: 200px;
background: green;
}
// 通过margin
.main {
margin-left: 200px;
margin-right: 200px;
height: 200px;
background: darkblue;
}
// 通过BFC
.main {
ovflow: hidden;
height: 200px;
background: darkblue;
}
</style>
第三种:flex布局
flex: 1的实现:代表了子项目将会占据所有的空闲空间
flex: 1其实是代表三个属性的简写,flex-grow、flex-shirnk、flex-basis
flex-grow: 该属性定义项目放大的比例,取值越大,代表向父级索取的宽度越大,默认值是1
flex-shirnk: 该属性代表项目缩小的比例,取值越大,代表缩小的比例越大,默认值是1
flex-basis: 该属性代表每个弹性盒子在主轴方向上所占用的空间大小,默认值0%
<!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>
<div class="box">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
<style>
.box {
display: flex;
}
.left {
width: 200px;
height: 200px;
background: red;
}
.right {
width: 200px;
height: 200px;
background: green;
}
.main {
flex: 1;
height: 200px;
background: rgb(194, 12, 139);
}
</style>
第四种:定位+margin
<!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>
<div class="box">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
</body>
</html>
<style>
.box {
position: relative;
}
.left {
position: absolute;
left: 0;
width: 200px;
height: 200px;
background: red;
}
.right {
position: absolute;
right: 0;
width: 200px;
height: 200px;
background: green;
}
.main {
margin-left: 200px;
margin-right: 200px;
height: 200px;
background: rgb(194, 12, 139);
}
</style>
第五种:table布局
<!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>
<div class="box">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
<style>
.box {
display: table;
width: 100%;
}
.left {
display: table-cell;
width: 200px;
height: 200px;
background: red;
}
.right {
display: table-cell;
width: 200px;
height: 200px;
background: green;
}
.main {
display: table-cell;
height: 200px;
background: rgb(194, 12, 139);
}
</style>
第六种:flex+calc
<!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>
<div class="box">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
<style>
.box {
display: flex;
width: 100%;
}
.left {
width: 200px;
height: 200px;
background: red;
}
.right {
width: 200px;
height: 200px;
background: green;
}
.main {
width: calc(100% - 400px);
height: 200px;
background: rgb(194, 12, 139);
}
</style>
JSON转化函数时的方法
浏览器缓存
什么是缓存?
缓存的原理是在首次缓存之后保存一份请求资源的响应副本,当用户再次发起相同请求时,如果判断缓存命中则拦截请求,将之前存储的响应副本返回给用户,从而避免从新向服务器发送请求
浏览器缓存主要分为两块,协商缓存和强制缓存
强制缓存
不会向服务器发送请求,直接从缓存中读取资源
使用强制缓存在响应头中的配置
express:响应头中设置过期时间,如果在过期时间之内,则命中缓存
cache-control:有以下几个值的选项
max-age:在设置的时间之内,不会再次发起请求
-no-cache:可以在本地进行缓存,但每次发请求时,都要向服务器进行验证,如果服务器允许,才能使用本地缓存。
-no-store:禁止浏览器缓存数据
-public:可以被所有用户缓存资源,包括终端用户和中间的代理服务器
-private:只能被终端的浏览器用户缓存
注:
1、express设置以分钟为单位的过期时间,max-age指明以秒为单位的过期时间
2、express优先级比cache-control低
协商缓存
需要向服务器发送请求,服务器会根据请求头中的参数来判断是否命中缓存,如果命中则返回304,通知浏览器从缓存中读取数据,如果没有命中,则重新请求资源,协商缓存可以解决强制缓存下资源不更新的问题
第一种方式:Last-Modify/If-Modify-Scene
浏览器第一次请求服务器时,服务器会在响应头中返回一个Last-Modify,是资源最后的修改时间标识,单位是秒,当浏览器再次向服务器发送请求时,会在请求头中加上If-Modify-Scene,如果If-Modify-Scene等于服务器中文件最后的修改时间,则返回给浏览器304,使用缓存,否则重新返回资源
第二种方式:Etag/If-None-Match
浏览器第一次请求服务器时,服务器会在响应头中返回一个Etag,是资源文件的hash值,当浏览器再次向服务器发送请求时,会在请求头中加上If-None-Match,如果If-None-Match等于服务器中文件中的hash,则返回给浏览器304,使用缓存,否则重新返回资源
Etag和If-None-Match的区别?
1、在精度上,Etag要优于If-None-Match,If-None-Match的时间单位是秒,如果在一秒内多次改动文件,那么他们的Last-Modify并没有体现出修改,而Etag每次都会改变,确保了精度
2、在性能上,If-None-Match要优于Etag,If-None-Match只需要记录时间,Etag则需要根据算法算出hash
3、在优先级上,服务器会优先考虑Etag
浏览器渲染
推荐看这位同学的总结,很全面:浏览器渲染流程 - 知乎
渲染器的核心就是把HTML、css、js转换为用户可以与之交互的网页,
按照渲染时间的顺序,流水线可以分为以下几个步骤:构建DOM树、样式计算、布局、分层、绘制、分块、光栅化、合成
1、构建DOM树
痛过HTML渲染器将HTML字节流转换为DOM树
2、解析css,生成cssom树
3、根据生成的DOM树和cssom构建一个渲染树
4、接下来是布局(回流),来计算每个模块的大小、颜色和位置
5、最后一步就是绘制,根据计算得出来的页面绘制到浏览器上
通过渲染过程可做的性能优化
1、减少http请求的次数
2、资源合并压缩
3、减少dom操作,否则会引起回流和重构,多操作js
inline-block会有什么问题
1、使用display: inline-block布局块级元素,会使元素之间有空隙
解决方法:
1、可以使元素写在一行,解决空隙
2、或者在父元素中将字号设置为0
2、也有可能会出现上下错位的问题
解决办法:
1、让两个div高度相同
2、使用vertical-align: top进行对齐
content-type的值
异步任务的执行时间可能会超过所设置的时间
借鉴博文:setTimeout不准时?你大意了_onmessage时间不稳定-CSDN博客
解决超时第一种方法:
思路:获取最开始的时间,然后轮询去查看,如果时间符合就执行
const loop = (delay, cb, startTime) => {
const now = Date.now()
if (now - startTime > delay) {
cb()
return
} else {
loop(delay, cb, startTime)
}
}
const startTime = Date.now()
loop(5000, cb, startTime)
解决超时第二种方法:Web Worker
解决超时第三种方法:window.requestAnimationFrame()
思路:告诉浏览器你需要执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数,回调函数执行次数一般是每秒60次,也就是16.8ms执行一次
const loop = (delay, cb, startTime) => {
const now = Date.now()
if (now - startTime > delay) {
cb()
return
} else {
requestAnimationFrame(loop(delay, cb, startTime))
}
}
const startTime = Date.now()
loop(5000, cb, startTime)
cookie设置以及哪个属性可以不让js修改
name:cookie的名字,一旦创建,无法修改
value:cookie的值
Domain:设置cookie在哪个域名下是有效的
Path:设置域名后的子路径
Expiress/Max-age:cookie的超时时间,当到达此时间后,cookie失效,不设置的话,默认值是session,当网页关闭后就失效
Size:cookie的大小,单位是字节,谷歌浏览器限制cookie最多150条,最大4096字节
HttpOnly:设置为true,不允许修改cookie,也不能获取cookie的值,但发送请求时还是会带上
Secure:设置为true,浏览器只会在https等安全协议下进行传输
Partition Key:限制第三方的cookie
设置为strict:完全限制第三方的cookie
设置为Lax:get请求可以携带cookie,设置Lax或者strict基本可以杜绝CSRF攻击,是谷歌浏览器的默认设置
设置为None:不限制
Priority:定义了low/medium/high三种优先级,当cookie的存入超出限制后,会清除掉低优先级的cookie
前端项目的安全问题
快速排序
核心思想:
1、会先找到一个对比值,一般可选中数组的第一个元素,也就是下标为0的
2、需要连个下标值,即最左端的下标和最右端的下标
3、拿出最右侧的值和对比值进行对比,若是大于,此值不移动,将右侧的下标减减进行移动,然后再次对比,若是还大于就继续减减,否则将值移动到左端下标处
4、经过第三个步骤,开始移动左侧的下表,和中心值进行对比,若是小于,将小标加加向右移动,然后再次对比,若是还小于就继续加加,否则将值移动到右端下表处
5、后面的步骤也是依旧进行递归比对,直到比对的长度为1
时间复杂度
推荐看这个视频,讲解的很好懂:小学生也能看懂的时间复杂度(大概吧)_哔哩哔哩_bilibili