1、当你输入一个url的时候发生了什么?
加载过程
1、首先DNS服务器会对这个域名进行解析,解析为ip地址。
2、然后浏览器根据ip地址向服务器发起请求,(包括TCP连接之类的)
3、服务器收到请后后返回数据
渲染过程
1、获取html文本,并渲染成dom tree
2、获取css文本,并渲染成cssom tree
3、遇到图片,视频等资源,会去加载,但不会阻塞渲染html和css
4、把他俩整合成一个render tree,渲染树
5、根据render tree渲染页面,
6、在渲染过程中如果有js代码,就先执行js代码,因为js可能会修改dom结构,所以他俩用的同一线程
7、直到render tree渲染结束
建议把css放在head里面,把js放在body最后
2、window.onload和DOMContentLoaded
document.onload = function(){
//dom加载完毕执行
}
window.addEventListener("load",function(){
//当dom渲染完毕,并且资源也加载好了,再执行
})
document.addEventListener("DOMContentLoaded",function(){
//当页面的dom渲染完毕后就执行,此时图片可能也没加载完毕
})
3、性能优化
3.1、性能优化的原则
多使用内存和缓存,或者其他的方法
减少网络请求,减少cpu计算
用空间换时间
3.2、性能优化方案
1、让加载更快
减少资源体积:压缩代码
减少访问次数:
- 合并代码:把css,js,图片(雪碧图/精灵图),合并起来
- SSR,服务端渲染:服务器先渲染好,然后发给浏览器
- 缓存:减少请求次数
让网络更快:CDN
2、让渲染更快
css放在head里面,js放在body下面
尽早执行js,使用DOMContentLoaded,不必要等页面资源加载完毕再渲染
使用懒加载(图片加载,上拉加载更多)
对DOM查询进缓存,对频繁的DOM操作合并再一起操作
节流throttle防抖debounce
3.2、性能优化事例
- 缓存:webpack的文件名counthash,文件内容不变,文件名字不变,服务器检测到url和文件名字都没变,就返回304.
- CDN:根据地域返回资源
- SSR:服务端渲染,比如加载一个新闻列表,服务器渲染完以后,返回一个页面,浏览器直接渲染。
- 懒加载:
<!--懒加载-->
<img id="pic" src="preview.png" realsrc="img.png"><img/>
<script>
//当页面滚动显示到这张图片时
let img = doucument.getElementById('pic')
img.src = img.getAttribute('realsrc')
</script>
- 减少DOM的查询次数,把频繁操作DOM的操作合并在一起:查询一次,保存在变量里面;创建一个frag片段document.createDocumentFragment(),等操作结束以后,把这个代码片段在加在页面上进行渲染。
- 尽早执行js,一些js操作,我们不需要等图片之类的资源加载完毕再执行,所以我们直接写在,DOMContentLoaded里面
3.3、手写防抖debounce
debounce防抖:比如在百度搜索栏中输入东西,当我们输入了以后,会给我们推荐相关内容,但是不能输入一个字就请求一次,所以要用到防抖,当用户输入结束500ms后在搜索
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="inp">
<script>
let inp = document.getElementById("inp")
//普通写法
let timeout = null
inp.addEventListener('keyup',function(){
if(timeout){
//如果还在继续输入东西,就把之前的定时器清空掉
clearTimeout(timeout)
}
timeout = setTimeout(()=>{
console.log(inp.value)
timeout = null
},500)
})
//函数封装
function debounce(fn,time=500){
let timer = null
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.apply(this,arguments)
timer = null
},time)
}
}
inp.addEventListener('keyup',debounce(function(){
console.log(this.value)
},500))
</script>
</body>
</html>
3.4、手写节流throttle
节流throttle:比如王者荣耀里面的技能,当我门在可能500ms点击10次,实际上他只触发一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="drag" draggable="true" style="width: 200px;height:100px;background:red;"></div>
<script>
let drag = document.getElementById('drag')
//普通写法
let timer = null
drag.addEventListener('drag',function(e){
if(timer){
return
}
timer = setTimeout(()=>{
console.log(e.offsetX,e.offsetY)
timer = null
},100)
})
//封装写法
function throttle(fn,timeout = 100){
let timer = null
return function(){
if(timer){
return
}
timer = setTimeout(()=>{
fn.apply(this,arguments)
timer = null
},timeout)
}
}
drag.addEventListener('drag',throttle(function(e){
//这里的e是通过arguments传过来的
console.log("@",e.offsetX,e.offsetY)
},200))
</script>
</body>
</html>
4、Web安全相关
4.1、XSS攻击,跨站脚本攻击
这是一种跨站工具,坏蛋通过我们网站的输入的地方,留言板啊,文章啊之类的地方,插入script脚本,来获取我们的cookie等相关信息,发送到自己的服务器上去。
<script>console.log(document.cookie)</script>
预防方法:通过用"<"和">"来替换"<“和”>",这样就不会被识别为脚本,建议在前端和后端都做处理,前端用这俩替换显示,后端用这俩替换保存数据。
4.2、XSRF攻击,跨站域请求伪造(不常见了)
比如我们获取到了一个支付的链接 xxx.com/pay?id=100 ,这时,我们把这个链接通过
img src=" xxx.com/pay?id=100"发送给别人,别人没看清就可能会支付
预防办法:重要的请求,使用post,还有加上支付验证等