1.JS上线之后在什么哪里运行?
1.运行环境即浏览器 (server端有nodejs)
2.下载网页代码,渲染出页面,期间会执行若干JS
3.保证代码在浏览器中: 稳定高效
2.网页是如何加载并渲染出来的
1.加载资源的形式
html代码
媒体文件,图片视频
JavaScript,css
2.加载资源的过程
1.DNS(Domid name server)解析: `域名`变为----> `IP地址`
2.浏览器根据IP地址向服务器发起http请求
3.服务器处理http请求,并返回给浏览器
3.渲染页面的过程
1.根据HTML代码生成DOM Tree
2.根据CSS 代码生成CSSOM
3.将DOM Tree 和 CSSOM 整合行程 Render Tree(渲染树)
4.遇到script则暂停渲染,优先加载并执行JS代码,完成再继续
5.直至吧Render Tree 渲染完成
3.网页加载和渲染的示例
为什么把css放在head中呢?
- 很简单,在执行渲染DOM的时候突然跳出来一个css样式,你本来的css样式就是默认,如果突然插入css样式文件,突然变成40px,会发生什么,这就是问题所在
为什么把js放在最后?
- 为了让用户先看到页面加载出来
示例一 // 根据html生成Dom树
<!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>webpack</title>
</head>
<body>p</body>
</html>
示例二 // 页面加载完要先执行css,css存放在head中先执行
<!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>webpack</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>test</div>
</body>
</html>
示例三 // 请把js放到最后执行 因为js会阻塞渲染过程,导致后续DOM无法加载,页面显示不全
<!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>webpack</title>
</head>
<body>
<div>test</div>
<script src="./index.js"></script>
<div>test</div>
</body>
</html>
示例四 // 渲染DOM之后 再渲染图片,并且不会停止
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack</title>
</head>
<body>
<div>test</div>
<p><img src="./1.png" /></>
<div>test</div>
</body>
</html>
4.网页加载和渲染相关的面试题
window.onloadd和DOMContentLoaded的区别?
window.onload 资源全部加载完之后才能执行,包括图片
DOMContentLoaded DOM 渲染完成即可,图片可能还没有下载
5.前端性能优化有哪些方式
性能优化原则
- 多使用内存,缓存或其他方法
- 减少CPU计算量,减少网络加载耗时
- 适用于所有编程的性能优化--------空间换时间
1.让加载更快
减少资源体积: 压缩代码
减少访问次数: 合并代码,SSR服务端渲染,缓存
使用更快的网络: CDN
2.让渲染更快
CSS放在head中, JS放在boay最下面
尽早开始执行JS,用DOMContentLoaded 触发
懒加载(图片懒加载,上滑加载更多)
对DOM查询进行缓存
频繁DOM操作,合并到一起插入DOM结构
节流throttle 防抖debounce
6.前端性能优化的示例
![图片转存失败,建议将图片保存下来直接上传
资源合并
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
<script src="assign.js"></script> // 与其请求三次资源,不如合并为一个
缓存
1.在webpack配置时候,静态资源加hash后缀,根据文件内容计算hash
2.文件内容不变,hash不变,url就不变
3.url和文件不变,则会自动触发http缓存机制,返回304
CDN
像一些css,js使用cdn, 可以大大提高访问速度
SSR
服务端渲染: 将网页和数据一起渲染一起加载
非SSR(前后端分离): 先加载网页,再加载数据,再渲染数据
7.手写防抖 debounce
- 监听一个输入框的,文字变化后触发change事件
- 直接用keyup 事件,则会频繁触发change事件
- 防抖: 用户输入结束或者暂停的时候,才会触发change时间
<input id="input1" type="text">
<script>
const input = document.getElementById('input1')
let timer = null;
input.addEventListener('keyup', () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
// 模拟触发 change事件
console.log(input.value)
// 清空定时器
timer = null
}, 500)
})
</script>
// 封装之后再使用
const debounce = (fn, delay = 500) => {
// timer 是在闭包中的
let timer = null;
// 闭包场景: 1.函数做为返回值 2.函数作为参数
return () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
// 使用 不传delay 默认500ms
input.addEventListener('keyup', debounce(() => {
console.log(input.value);
}))
8.手写节流 throttle
- 拖拽一个元素时候,要随时拿到该元素被拖拽的位置
- 直接用drag事件,则会触发频繁,很容易导致卡顿
- 节流: 无论拖拽速度多快,都会每隔100ms触发一次
<style>
#div1 {
width: 200px;
height: 200px;
background-color: #ccc;
font-size: 24px;
}
</style>
<div id="div1" draggable="true">拖拽</div>
<script>
const div1 = document.getElementById("div1");
let timer = null;
div1.addEventListener('drag', (e) => {
if (timer) {
return
}
timer = setTimeout(() => {
console.log(e.offsetX, e.offsetY);
timer = null;
}, 1000)
})
const throttle = (fn, delay = 1000) => {
let timer = null;
return () => {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
div1.addEventListener('drag', throttle((e) => {
console.log(e.offsetX, e.offsetY);
}))
</script>
9.如何预防 xss 攻击
- 常见的web前端攻击方式有哪些?
- 1.XSS跨站请求攻击
- 2.XSRF跨站请求伪造
比如一个博客网站,发表一篇博客,其中嵌入<script> 脚本
1.脚本内容: 获取cookie,发送到我的服务器(服务器配合跨域)
2.发布这篇博客,有人查看它,我轻松收割访问者的cookie
解决方法:
1.替换特殊字符,比如< 变为< >变为>
2.<script> 变为<script> 直接显示,不会做为脚本执行
3.前端显示的时候替换,后端存储的时候替换
10.如何预防 xsrf攻击
1.使用POST接口
2.增加验证,例如密码,短信验证登录,指纹等安全措施