一、 vue 面试题
1.1 keep-alive理解
1.2 父子组件传值
- 子组件通过props接收父组件穿过来的数据
- 子组件通过$emit 触发父组件中的方法
1.3 $nextTick的理解和作用
-
nextTick 本质上是一个延时器。vue用三种方案实现nextTick。
promise、setTimeOut
、HTML5中的APIMutationObserver
-
有时dom还没渲染结束,确想对dom进行一些操作时,可能实际结果与预期不符,可以将对dom的操作或者数据变化后的一些操作放在 $ nextTick函数中进行逻辑的处理。例如:查看切换后的结果,就可以在切换函数中使用$nextTick函数,一般是需要对dom进行操作
-
像对canvs一类的标签,无法监测到数据变化内容变化的标签,就需要在nextTick中进行重绘。因为对于虚拟dom来说,没有发生变化。
methods: { // 函数执行顺序 点击事件函数(数据data发生变化)——》beforeUpdate函数——》updated函数——》nextTick函数 // 更新的本质是数据发生了变化 changeMsg(){ this.form.username = 'lxf' const that = this this.$nextTick(function() { // 仅在整个视图都被重新渲染之后才会运行的代码 console.log(that.$refs['userName'].innerHTML + 'changeMsg') }) } }
1.4 虚拟dom和真实dom
- 本质上 Virtual Dom 是一个 JavaScript 对象,通过采用对象的格式来表示真实的dom结构。
可以有效的减少页面渲染的次数,减少修改DOM的重绘重排次数,提高渲染性能
- 在数据发生变化前,虚拟dom都会缓存一份,在数据发生变化时,新生成的虚拟DOM与缓存的虚拟DOM进行比较(采用diff算法比较),精准更新发生变化的节点,而没有发生变化的直接通过原先的数据进行渲染。
- 可以减少对dom的操作,提高程序性能;减少页面重绘和回流;跨平台,虚拟DOM本质上是javascript的一个对象,不依赖真实的平台环境。
- 虚拟DOM形成过程 template模板——》被编译器 compiler编译成渲染函数 ——》在挂载前(beforeMount)调用render函数并返回虚拟DOM对象,在beforeMount后、mounted前通过patch函数转为真实DOM。相关知识ast语法树
1.5 怎样提高vue的性能
二、 vue 生命周期面试题
2.1 vue生命周期理解
2.2 第一次加载页面会触发的钩子函数
beforeCreate created beforeMount mounted
2.3 常用钩子函数适用的场景
- created :此时数据和方法已经配置完毕,可以进行方法调用和数据使用。
- mounted : 此阶段dom元素已经挂载结束,可以获取页面中的元素进行操作。如果有子组件建议和
vm.$nextTick
搭配使用。 - deforeDestroy :实例销毁前可以进行一些善后处理,如:清除计时器、清除非指令绑定的事件等等…’
2.4 vue 父子组件的渲染顺序
父组件beforeCreated ——》 父组件created ——》父组件beforeMount ——》第一个子组件beforeCreate ——》第一个子组件created ——》第一个子组件beforeMount ——》第N个子组件beforeCreate ——》第N个子组件created ——》第N个子组件beforeMount ——》第一个子组件mounted ——》第N个子组件mounted ——》父组件mounted
2.5 vue父子组件销毁的顺序
父组件beforeDestroy -——》第一个子组件beforeDestroy ——》第一个子组件destroyed -——》第N个子组件beforeDestroy ——》第N个子组件destroyed ——》父组件destroyed
三、 vuex面试题
3.1 vuex是什么
答:vuex是Vue框架的状态管理。需要创建store.js文件,在main.js中引入并 注入。下面是main.js 文件
3.2 vuex属性及使用方法
四、 vue-router 面试题
4.1 vue-router是什么
vue-router是Vue管理路由的一个插件,即记录组件和路径的映射关系。
4.2 vue-router 有哪些常用的组件
- router-link :是一个路由导航的一个组件,和a标签的功能一样。当路由被激活时有一个激活的css类名(router-link-active),可以做导航高亮显示
- router-view :是一个function组件,将路由匹配到的视图组件渲染在router-view标签的位置。
4.3 vue-router的两种路由模式以及区别
- 两种模式 hash和history。默认是hash
- 共同点:url改变无需重新加载页面
- 区别
- hash路径前带#,history不带#> http://localhost/components/tabs (history)
http://localhost/#/components/noticeBar (hash值为 #/components/noticeBar) - hash模式下的http请求不会包含hash值
- hash支持低版本浏览器,history不是那么友好
- history模式部署需要后端配置,
当用户刷新页面时会向真的向服务器请求资源,并携带有url
,后端不做处理的话会报404。需要后端配置一下apache或是nginx的url重定向,重定向到入口文件(index.html)。 - 路由的哈希模式是利用了window.onhashchange事件,当url中的哈希值(#后面的值)发生变化,就会自动调用hashchange的监听事件,在hashchange的监听事件内可以得到改变后的url,这样能够找到对应页面进行加载
window.addEventListener('hashchange', () => { // 把改变后的url地址栏的url赋值给data的响应式数据current,调用router-view去加载对应的页面 this.data.current = window.location.hash.substr(1) })
- history利用的是HTML5 新增的 pushState() 和 replaceState() 方法,在原有的back、forward、go 的基础上,这两个方法提供了对历史记录进行修改的功能。pushState方法、replaceState方法,只能导致history对象发生变化,从而改变当前地址栏的 URL,但浏览器不会向后端发送请求,也不会触发popstate事件的执行
- 传统的路由指的是:当用户访问一个url时,对应的服务器会接收这个请求,然后解析url中的路径,从而执行对应的处理逻辑。这样就完成了一次路由分发;
而前端路由是不涉及服务器的,是前端利用hash或者HTML5的history API来实现的,一般用于不同内容的展示和切换
- hash路径前带#,history不带#> http://localhost/components/tabs (history)
4.4 路由跳转方式
4.5 导航守卫分类
4.5.1 全局守卫导航
4.5.1.1 全局前置守卫 beforeEach
作用:路由每次跳转前都会执行此函数。一般用于跳转前进行判断拦截,例如:是否登录
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes: []
})
router.beforeEach((to, from, next) => {
// to:即将要进入的目标 路由对象
// form:当前导航正要离开的路由
// next :执行下一步操作
// 判断是否登录
if (getToken()) {
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
next()
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
4.5.1.2 全局后置守卫 afterEach
作用:路由每次跳转结束都会执行此函数。
router.afterEach((to, from) => {// ...})
4.5.2 组件守卫导航
- beforeRouteEnter 导航确认之前调用,新的组件(页面)还没被创建。可以针对不同页面进行特殊处理。
- beforeRouteUpdate 动态路由发生变化时调用
- beforeRouteLeave 用户离开前调用
beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 console.log('beforeRouteEnter') next(vm => { // 通过 `vm` 访问组件实例 }) }, beforeRouteUpdate(to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` next() }, beforeRouteLeave(to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` console.log('beforeRouteLeave') next() },
4.5.3 路由独享守卫
-
在创建路由时写对应的路由守卫
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
五、 javascript
5.1 深拷贝
- 为什么需要深拷贝
希望在改变新数组(对象)时,不改变原数组(对象)。 - 造成需要深拷贝的原因
数据类型有两种:基本数据类型和引用数据类型。所有的变量都存在栈内存中,引用数据类型的变量存在栈内存,实际数据存在堆内存
。引用数据类型在栈内存中存储的只是一个内存地址。赋值时也是把这个地址赋值给另一个变量。 - 深拷贝的思路
- 判断数据源的数据类型,是数组还是对象,定义出返回的变量finalResult
- 循环数据源(for in 循环,数组对象都可循环)
- 判断每一项的数据类型
- 如果是数组或者对象,就再次调用函数,将当前数据当参数传入函数
- 如果是引用类型的其他数据,如Date、Error、RegExp、Set等,通过使用constructor属性创建对应的数据类型(
new 数据.constructor(数据)
)并进行赋值 - 剩余的直接进行赋值
- 最后将开始定义的变量finalResult 返回
- 实现深拷贝的方案
使用JSON.stringify和JSON.parse
,若有undefined、function,拷贝后丢失,Date、Error、RegExp等引用类型的数据会与初始数据不一样。
let obj = { username: "cat", age: 10, color: 'gary', sex: undefined } // 将对象转换为json字符串形式 let tempObj = JSON.stringify(obj); // 将转换而来的字符串转换为原生js对象 let newObj = JSON.parse(tempObj ); console.log(newObj) // {username: "cat",age: 10, color: 'gary',} newObj.age = 5; console.log(obj.age); // 10 console.log(newObj.age); // 5
-
使用插件lodash 相关代码
-
递归
-
使用Jquery的extend函数
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象let obj = { username: "cat", age: 10, color: 'gary', sex: undefined, arr: [1,2,3,4] } let newObj = $.extend(true,{},obj); newObj.arr[0] = 5; console.log(obj.arr[0]); // 1 console.log(newObj.arr[0]); // 5
-
使用concat函数 只能是数组的拷贝,不能拷贝对象
5.2 排序函数
- 冒泡排序
- 快速排序
- 选择排序
- 插入排序
- 归并排序
- sort函数排序
5.3 去重函数
- Set
- reduce函数
- Map
- for循环 + 定义数组变量 + Array.includes(判断是否存在的任意函数)
- filter + Map
- filter + Array.includes
5.4 常用的es6方法
- 箭头函数 ()=>{}
- 扩展运算符 …
- 解构赋值 {total, rows} = res.data
- Map
- Set函数
- cosnt
- let
- 模板字符串
5.5 闭包
5.5.1 闭包定义
- 闭包:可以在外部访问函数内部的变量,一般是返回一个函数,函数内部引用了变量
- 内存泄漏:指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory
- 内存溢出:指程序在申请内存后,无法释放已申请的内存空间,内存泄露堆积会导致内存被占光
5.5.2 闭包的特点
- 持久性存储:当内存中的值失去引用时便会被垃圾回收机制处理释放内存,但因为闭包导致某块内存永远存在。
正常情况f1() 执行结束后,其生命周期就结束了,外部无法访问到变量a,但是因为f2的引用赋值给了fn,所以f2被保留了下来,又因为f2中的a依赖f1,所以f1也被保留了下来。因此在f1执行结束后还可以访问到变量alet fn = null; function f1() { let a = 666; function f2(){ console.log(a); } fn = f2; } f1() fn()//-------666
- 导致内存泄漏:闭包会将数据持久性存储,每次外部函数触发,都会开辟一块新的内存,函数调用的那块内存会被长久占用而不能被垃圾回收机制释放,就会导致内存泄漏。
每次调用都是重新开始,重新开辟的空间,之前的也不会被释放function init() { var a = 0; return function (){ console.log(++a); } } let resA = init(); let resB = init(); resA()//----1 resA()//----2 resB()//----1 resB()//----2
5.5.3 闭包中是否可以使用await
5.6 函数的this指向问题
5.7 冒泡和捕获**
5.7.1 定义
- 事件冒泡:事件由子元素传递给父元素的过程就做事件冒泡。
- 事件捕获:事件由父元素传递给子元素的过程叫做事件捕获。
5.7.2 区别
- 冒泡和捕获就是事件的执行顺序不一样。
- 冒泡是先子元素,在层层向外层触发(false)
- 捕获是先外层触发,再层层向内层触发,直到触发的元素(true)
5.7.3 阻止事件冒泡的方式
- event.stoppropagation() 阻止事件冒泡
- addEventListener(()=>{}, false)
- vue 修饰符 .stop
5.7.4 阻止默认行为
- event.preventDefault()
- vue 修饰符 .prevent
5.7.5 button的默认行为
- button的 type = submit 默认提交表单
- button的type = reset 默认行为表单重置
- button的type = button 就会执行do nothing
- 未定义button type的,IE浏览器默认的是button类型,其他浏览器默认的是submit类型的
5.8 v-if和v-for
5.8.1 v-if和v-show 的区别
- 共同点:都可以控制元素的显示与隐藏
- 不同点
- v-if 但条件为false时不渲染元素,只当条件为true时才显示
- v-show 是条件不管是否为true都渲染,当为true时再显示
5.8.2 vue2 和vue3 关于vi-if和v-for的区别
- vue2 中v-for优先级高于v-if, 造成性能上的浪费,
- vue3 v-if比v-for的优先级高,导致v-if 使用不了v-for中的变量
5.8.3 如何解决v-for和v-if 不作用于同一个元素上
- 使用computed 过滤出需要展示的数据
- 使用template 将for 循环包裹
- 使用v-show
六、 计算机网络
6.1 常见的浏览器内核
- IE浏览器内核:
Trident
内核,也是俗称的IE内核; - Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是
Blink
内核 - Firefox浏览器内核:
Gecko
内核,俗称Firefox内核; - Safari浏览器内核:
Webkit
内核 - Opera浏览器内核:最初是自己的
Presto
内核,后来是Webkit,现在是Blink
内核 - 360浏览器、猎豹浏览器内核:IE+Chrome双内核
- 搜狗、遨游、QQ浏览器内核:Trident(兼容模式)+Webkit(高速模式);
- 百度浏览器、世界之窗内核:IE内核;
- 2345浏览器内核:以前是IE内核,现在也是IE+Chrome双内核;
6.2 浏览器引擎(内核)
- 浏览器内核原来是指
渲染引擎
和js引擎
,随着js引擎越来越独立,现在内核更倾向于渲染引擎。 - 浏览器内核负责HTML解析、布局、渲染等相关工作,JavaScript引擎负责解析、执行JavaScript代码。
- 浏览器地址栏输入 chrome://version 进行查看js引擎和浏览器内核(部分可以看见)
6.3 输入ip到页面显示的过程
- 用户输入域名(IP地址),过DNS解析找到对应的ip地址
- 根据ip地址向服务器发送请求
- 建立TCP连接(三次握手)
- 连接建立完成后,发送http请求
- 服务器根据请求作出http响应
- 浏览器得到响应的内容,进行解析渲染并展示
- 断开连接(四次挥手)
6.4 浏览器渲染的过程
- 解析html构建DOM树(DOM Tree)
- 解析css构建CSS规则树(CSSOM Tree)
- 将DOM树和CSS规则树结合在一起构建成渲染树(Render tree)
- 根据生成的渲染树,进行回流(reflow),得到节点的几何信息(大小、位置等)
- 重绘(repaint):根据回流得到的几何信息,得到节点的绝对像素
- display:将像素发送给GPU,最后通过调用操作系统Native GUI的API绘制,展示在页面上
- 遇到<script>则暂停渲染,优先执行js,然后再继续渲染(因为js执行和渲染引擎公用一个进程,原因是js可 能做了一些dom操作,一般会把js放到页面的底部)(发生回流,重绘)
6.5 三次握手
6.5.1 三次握手过程
- 客户端给服务端发送一个同步(SYN)报文请求建立连接,此时客户端进入
SYN_SENT
状态 - 服务器接收到后会给客户端发送一个确认(SYN - ACK)报文,服务端进入
SYN_RCVD
状态 - 客户端接收到后又发送一个确认(ACK)报文。此时客户端进入
ESTABLISHED
状态.当服务端接收到客户端的第三次握手后也就进入ESTABLISHED状态
6.5.2 三次握手的作用
- 作用:
确认双方的接收和发送功能是否正常,即传输线路是否正常
- 原因:服务端接收到客户端的报文表明客户端端的发送功能和服务端的接收功能正常;浏览器接收到服务端的报文表明浏览器的发送接收、服务器的发送接收功能都正常;服务端不知道自己发送功能是否正常,所以需要浏览器再发送一次应答报文给服务器。
三次握手第三次可以携带数据,前两次不行
。
6.5.3 两次握手造成的后果
- 后果:
会造成服务端的系统资源浪费
。 - 原因:如果客户端发送连接请求,因报文丢失而未收到确认,客户端就会再次发送请求。收到确认后建立连接,数据传输结束,断开连接。可能第一次的请求因在某些网络节点长时间滞留,导致在释放连接后到达服务端,此时服务端以为是客户端再次请求连接,服务端向客户端发送确认报文,等待客户端发送数据,客户端迟迟不发送数据,就会造成服务端无法正常关闭。
6.5.4 半连接队列
- 目的:存放未建立起连接状态的请求
- 定义:服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
6.5.5 全连接队列
- 定义: 完成三次握手建立起连接的放在全连接队列。
- 注意:全连接队列满了会造成丢包问题。
6.5.6 服务端SYN - ACK包重发次数问题
在服务端发送完SYN - ACK包后,没有收到客户端的确认包,服务端就会进行首次重传,一段时间内还是未收到确认包,进行第二次重传,直到重传达到系统设置的最大次数,系统才会把这些连接信息从半连接队列中删除。一般重传间隔时间为指数增长,例如:1s 2s 4s 8s…
6.5.7 SYN攻击
服务器端的资源分配是在第二次握手分配的,客户端的资源分配是在第三次握手时分配的。
所以服务器端容易受到SYN泛洪攻击。就是在短时间内伪造大量不存的IP地址向Server(服务端)发送SYN包,Server则发送确认包,等待client确认,由于IP地址不存在,Server需要不断的重发确认包,直至超时。这些伪造的SYN包长时间占用半连接队列,造成正常的SYN请求因队列满而被丢弃。
6.5.8 常见的防御SYN攻击方法:
- 缩短超时(SYN Timeout)时间,通过缩短重传超时时间
- 增加半连接状态数量
- 采用SYN cookies 技术: 半连接队列被塞满,采用SYN cookies可以使SYN请求不被丢弃,而是用加密的方式标记半连接状态
- 过滤网关(防火墙、路由器)防护:网关超时设置、SYN网关、SYN代理
6.6 四次挥手
6.6.1 四次挥手过程
- 客户端发送一个FIN报文给服务端,告诉服务端我要断开连接,客户端进入终止等待1(FIN-WAIT1)
- 服务端接收到FIN报文,会给客户端发送一个ACK报文,表述我接收到你的请求了,服务器端进入CLOSE_WAIT状态
- 客户端收到服务的ACK包后进入终止等待2(FIN-WAIT2),等到服务端发送断开连接的报文
- 服务器进入CLOSE_WAIT后说明服务器准备关闭连接(但是需要处理完之前的未处理的数据),当服务器调用close方法真正准备关闭连接时,会向客户端发送FIN,这时服务器进入 LAST_ACK状态(等待最后一个ACK到来)。
- 客户端收到服务端的FIN报文,会向服务端发送一个ACK报文,此时客户端进入TIME_WAIT状态。
- 当服务器收到来自客户端的ACK(对自己提出FIN请求的回应)后,就会彻底关闭变为CLOSED状态。
6.6.2 MSL是什么
MSL是Maximum Segment Lifetime的缩写,翻译过来就是 最长报文段寿命
。它是任何报文在网络中存在的最长时间,超过这个时间报文就会被丢弃。
6.6.3 为什么要等2MSL后才能关闭连接
- 为了确保客户端发送的最后一个ACK报文能够正常到达服务端。
客户端发送的最后一个ACK包可能丢失,如果服务端在LAST_ACK状态收不到客户端发来的ACK确认包,服务端就会重传FIN - ACK 包,客户端就会重新发送ACK包。重新计时,过2MSL时间关闭。如果客户端不等待2MSL,可能造成服务端接收不到客户端的ACK报文,导致服务端无法正常进入CLOSED状态。TIME_WAIT状态就是为了重发可能丢失的ACK报文
- 防止“已失效的连接请求段报文”出现在新的连接中
客户端发送完最后一个ACK报文,经过2MSL时间,网络中关于此次连接的报文都会被丢弃,就不会出现在下一个新的连接中出现旧的连接报文请求。
6.7 三次握手和四次挥手总示意图
6.8 HTTP、HTTPS 协议
6.8.1 定义
http
协议是超文本传输协议(Hypentext Transfer Protocol)的简写,是一个简单的请求-响应
协议,它通常运行在TCP之上。他指定了客户端可能发送什么样的消息给服务器,服务器又该给客户端作出什么样的响应。
https
协议是超文本传输安全协议(Typentext Transfer protocol secure)的简称,是在http协议的基础上通过传输加密
和身份认证
保证了传输过程的安全性,是以安全为目标的http通道。https是在htpp的基础下加入SSL
,https的安全基础就是SSL。http和https不同之处就在于https的默认端口(443)
和加密/身份验证层
(http和TCP之间),https协议一般用于交易支付、信息敏感等方面
6.8.2 https 相关定义
- 身份认证:
- 定义:身份认证又称为“验证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。
- 实现方法:
- 基于共享密钥的身份验证
- 基于生物学特征的身份验证
- 基于公开密钥加密算法的身份验证
- SSL:SSL是安全套接层(Secure Socket Layer)的简写,是一种网络安全协议,Netscape(网景)公司率先采用的;SSL是在传输通信(TCP/IP)上实现的一种安全协议,采用的是公开密钥技术
6.9 HTTP(数据)请求方式
6.9.1 http请求格式(结构)
6.9.1.1 概述
-
http的请求是成对的,有request就有response。我们称之为
上行请求
和下行响应
,不管哪种请求,都是“报头” + “报文”的形式传输数据。 -
报头 = 请求行 + 请求头
-
报头一般都是存放一些信息,比如客户的信息、cookie、访问时间等
-
一般上行请求的上行报文是空的,下行响应的下行报文是html的代码
-
常见的请求方式 get、post、put、delete,还有options、connect、trace、head
6.9.1.2 http 请求报文格式
- http 请求报文组成部分
- 请求行
- 请求头
- 空行
- 请求数据
6.9.1.3 http 请求报文实例
6.9.1.4 http 请求响应格式
- http 请求报文组成部分
- 状态行
- 响应头
- 空行
- 响应数据
6.9.1.5 http 请求响应实例
6.9.1.6 常见的首部字段
原文链接:HTTP报文头部字段大全
-
通用首部字段:请求和响应都有
- 常见的首部字段有
Date、Connection、Cache-Control、Transfer-Encoding 、Pragma
- 字段解释
-
Date:
创建报文时间 -
Connection:
决定当前的事务完成后,是否会关闭网络连接- keep-alive: 网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成;
- 从 HTTP/1.1 版本开始,所有连接默认为持久连接。
-
Cache-Control:
缓存的控制:从缓存性
、到期时间
、重新验证&重新加载
三个方面控制- 缓存性
- no-cache: 会强制验证数据的有效期,以防止获取到过期资源。
- no-store: 会禁止缓存服务器缓存数据。(一般意味着数据中含有机密信息
- only-if-cached: 仅从缓存服务器获取数据,保证请求绝不会达到源服务器,如果缓存服务器没有该资源,则返回状态码504(GateWay Timeout)
- public: 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存
- private: 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)
- 到期时间
- max-age: 设置缓存存储的最大周期,超过这个时间缓存被认为过期 (单位秒)。客户端只接收缓存时间`max-age的数据
- s-maxage: 覆盖 max-age 或 Expires 字段,但它只适用于共享缓存(例如代理服务器),私有服务器会忽略这个字段。
- max-stale: 表示客户端愿意接收一个过期的资源,只要资源的过期时间小于 max-stale 的值
- min-fresh: 表示客户想要的资源至少在指定的秒数内仍然是新的
注意事项:
HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略
- 重新验证&重新加载
- proxy-revalidate:指令要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性,与 must-revalidate 的功能相同
- no-transform:
禁止对资源进行转换。
Content-Encoding ,Content-Range ,Content-Type 标头不得被代理修改。例如,一个不透明的代理可能会在图像格式之间进行转换,以节省缓存空间或减少慢速链接上的流量,而这个行为会被 no-transform 禁止。
- 示例
- 禁止缓存:
Cache-Control: no-store
- 缓存静态资源,例如图像,CSS 文件和 JavaScript 文件:
- Cache-Control: public, max-age=31536000
- 需要重新验证:指定 no-cache 或 max-age=0, must-revalidate 表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。
- Cache-Control: no-cache 0
- Cache-Control: max-age=0, must-revalidate
- 禁止缓存:
- 缓存性
-
Transfer-Encoding:
规定传输报文时采用的编码方式- chunked :
数据以一系列分块的形式进行发送
。在每一个分块的开头需要添加当前分块的长度(十六进制),后面紧跟着 ‘\r\n’ ,之后是分块本身,后面也是’\r\n’ 。终止块是一个常规的分块,不同之处在于其长度为 0。
- gzip:
表示采用 Lempel-Ziv coding (LZ77) 压缩算法,以及 32 位 CRC 校验的编码方式
。这个编码方式最初由 UNIX 平台上的 gzip 程序采用。处于兼容性的考虑,HTTP/1.1 标准提议支持这种编码方式的服务器应该识别作为别名的 x-gzip 指令。 - compress:
采用 Lempel-Ziv-Welch (LZW) 压缩算法
。这种内容编码方式已经被大部分浏览器弃用。 - deflate:
采用 zlib 结构,和 deflate 压缩算法
。 - br: 表示采用 Brotli 算法的编码方式。
- identity:
用于表明自身未经过压缩和修改
。 注意:
Transfer-Encoding 是一个逐跳传输消息首部,即仅应用于两个节点之间的消息传递。如果想要将压缩后的数据应用于整个连接,那么应该使用端到端传输消息首部 Content-Encoding 。
- chunked :
-
Pragma:
HTTP/1.0 的 Cache-Control- Pragma 是一个在 HTTP/1.0 中规定的通用首部
- 在HTTP/1.1 协议被 Cache-Control 代替
- 现在它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器。
-
- 常见的首部字段有
-
请求首部字段:
- Accept:
用来告知服务器可以处理的内容类型
- Accept-Charset:
用于声明客户端可以处理的字符集类型
- Accept-Encoding:
用于声明客户端能够处理的编码方式
- Accept-Language:
用于声明客户端可以理解的语言
- Authorization:
用于提供给服务器验证身份的凭据,允许其访问受保护的资源
- Expect:
客户端发送带有 Expect 消息头的请求,等服务器回复后再发送消息体
- From:
附带一个电子邮箱地址
- Host:
指明本次请求的目标服务器主机名和端口号。
- User-Agent:
发起HTTP请求的客户端信息
。可用于判断当前客户端的类型 - Range:
Range 字段用于分批请求资源,下面的示例表示请求获取从第 5001 字节至第 10000 字节的资源。
- Range: bytes=5001-10000
- If-Match:
比较实体标记(ETag),条件为真再执行。
形如 If-xxx 这种样式的请求首部字段,都可称为条件请求。服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。 - If-Modified-Since:
用于确认客户端拥有的本地资源的有效性
。服务器在收到带有 If-Modified-Since 字段的请求后,会将该字段值和资源更新时间做比较,若资源没有更新,则返回 304 状态码(Not Modified)。 - If-None-Match:
与 If-Match 的作用相反
- If-Range:
资源未更新是发送实体Byte的范围请求
。If-Range HTTP 请求头字段用来使得 Range 头字段在一定条件下起作用:当字段值中的条件得到满足时,Range 头字段才会起作用。字段值中既可以用 Last-Modified 时间值用作验证,也可以用 ETag 标记作为验证,但不能将两者同时使用。 - If-Unmodified-Since:
与 If-Modified-Since 作用相反
- Max-Forwards:
用于限制 TRACE 方法可经过的服务器(通常指代理服务器)数目。
发送包含首部字段 Max- Forwards 的请求时,该字段以十进制整数形式指定可经过的服务器最大数目。每经过一个服务器,Max-Forwards 的值减 1。当服务器接收到 Max-Forwards 值为 0 的请求时,则不再进行转发,而是直接返回响应。 - Proxy-Authorization:
用于客户端和代理服务器之间的认证
。规定了客户端与代理服务器的认证方式 - Referer:
对请求中URL的原始获取方法
。Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。 - TE:
表明客户端能够处理的传输编码方式及相对优先级
- Accept:
-
响应首部字段
- Accept-Ranges:
表明服务器是否支持范围请求
。可以处理范围请求时指定字段值为 bytes,反之则为 none - Age:
表明资源在代理服务器缓存了多久,以秒为单位
- ETag:
ETag 是资源的唯一标识符,使用 ETag 能快速确定资源是否发生过变化
- Location:
用于将页面重定向至新的地址
- Proxy-Authenticate:
会把由代理服务器所要求的认证信息发送给客户端
- Retry-After:
用于告知客户端应该在多久之后再次发送请求
- Server:
表明服务器的软件和版本信息
- WWW-Authenticate:
定义了应该使用何种验证方式去获取对资源的连接
。规定了客户端与服务器的认证方式。
- Accept-Ranges:
-
报文实体字段
- Allow:
用于枚举资源所支持的 HTTP 方法的集合
- Cotent-Encoding:
消息文本的编码类型
- Cotent-Language:
用来说明服务器希望访问者采用的语言或语言组合级
- Content-Length:
用于指明发送给客户端的消息主体的大小,用十进制数字表示
- Content-Location:
对应资源的URL。
- Content-Range:
用来表示一个数据片段在整个文件中的位置
- Content-Type:
用于告知客户端响应报文内容的内容类型
- Expires:
用于告知客户端缓存的失效日期
- Last-Modified:
资源最后一次修改的时间
- Cookie:
客户端在向服务器发 HTTP 请求时附带 Cookie 以获得服务器的认证
- Allow:
6.9.1.7 报文头部字段的转发策略
- 一个 HTTP 请求要跨过多个代理服务器,经过多次代理服务器的转发才能到达目标服务器。
- 代理服务器做转发时,对原HTTP报文头部字段有两种处理方式:
- 逐跳策略:单次转发有效。
- 到端策略:一直有效,确保字段被发送到目标服务器。
- 以下字段为逐跳策略,其他字段都是端到端策略
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- Trailer
- TE
- Transfer-Encoding
- Upgrade
6.9.2 get 请求
- 定义:从服务器的数据库中获取已存在的数据,不对数据进行任何的修改、新增、删除等操作;对应数据库的select操作;对数据不造成影响;一般用于获取信息操作
- 说明
- 请求参数会拼接在请求URL的后面,多个参数以&连接
- 安全性低,信息会在地址栏显示
- 速度快,一般用于信息不敏感的请求,或者是将参数加密处理
- 传递数据量小,大约4kb(不同浏览器有有差异)
- HTTP 协议对get请求的URL没有大小限制,但不同浏览器对URL有不同的长度限制
- 方便分享
6.9.3 post 请求
- 定义:将数据发送到服务器 上,创建或者更新数据,对应数据库的insert/updade操作;会对数据造成影响;一般用于初次添加信息、修改信息、表单提交等操作
- 说明
- 请求参数放在body请求体内(上行报文)
- 安全性比get高一些,但抓包软件还是会抓到post内容,可以考虑加密
- 传递的数据量大,对请求数据长度没有限制
- 请求不会被缓存,也不会保留在浏览器的历史记录中
- 用于像密码等安全性要求高的场合,需要提交大量数据的场合,如发布文章、文件上传
- post 默认数据提交上限是8M,可以修改
- 不方便分享,因为无法携带参数
6.9.4 put 请求
- 定义:向服务器上传或者更新资源。对应数据库的update 操作
- 说明:和post相似,不过 put只能更新,post既可以创建,又可以更新
6.9.5 delete 请求
- 定义:删除服务器上的数据。对应数据库的delete 操作
6.9.6 options 请求
options请求实际上就是预检请求,可以检测服务器允许的http请求
6.9.6.1 options 请求发生的原因
- 主动发送options请求(一般不这么操作)
- 复杂请求触发了options 请求
- 跨域请求触发了options 请求
6.9.6.2 简单请求和复杂请求
- 简单请求(同时满足)
- 请求方式是 get、post、head
- http请求头头部只能是以下集合的几个字段(称为首部字段)
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type的值是以下几个之一
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 请求中的任意 XMLHttpRequestUpload对象均没有注册任何事件监听器
- 请求中没有使用 ReadableStream对象。
- 复杂请求
- 剩余的其它五种请求方式
- 人为设置了简单请求http头部 集合之外的首部字段,即自定义头部; 实际开发中一般都是在头部header添加token等一些信息,用于用户信息验证,这就是自定义头部
- Content-Type 不是application/x-www-form-urlencoded、multipart/form-data、text/plain这三个值
6.9.6.3 简单请求和options请求区别
-
简单请求浏览器会直接请求,并在请求头添加origin字段,说明本次请求来源(协议+域名(IP) + 端口号)。服务器根据origin的值判断是否同意本次请求;服务器返回的响应头中的信息中会多三个关于CORS(跨域资源共享)的字段
- Access-Control-Allow-Origin:该字段是必须的,* 表示接受任意域名的请求,还可以指定域名-
- ccess-Control-Allow-Credentials:该字段可选,是个布尔值,表示是否可以携带cookie,(注意:如果Access-Control-Allow-Origin字段设置*,此字段设为true无效)
- Access-Control-Allow-Headers:该字段可选,里面可以获取Cache-Control、Content-Type、Expires等,如果想要拿到其他字段,就可以在这个字段中指定。比如Token
-
options请求
-
官方将头部带自定义信息的请求方式称为带预检(preflighted)的跨域请求。
-
在实际调用接口之前,会首先发出一个OPTIONS请求,称为预检,浏览器会先询问服务器,当前网页所在域名是否在服务器的许可名单之中,服务器允许之后,浏览器会发出正式的XMLHttpRequest请求,否则会报错。(备注:之前碰到预检请求后端没有通过,就不会发正式请求,然后找了好久原因,原来后端给忘了设置…)Java后端实现拦截器,排除Options,以下是JAVA的代码片段
-
在OPTIONS请求中,通过
request-header
将Access-Control-Request-Headers
与Access-Control-Request-Method
发送给后台,另外浏览器会自行加上一个Origin
请求地址。 -
服务端在接收到预检请求后,根据资源权限配置,在
response-header
头部加入- access-control-allow-origin(允许跨域请求的域)
- access-control-allow-methods(允许跨域请求的请求方式)
- access-control-allow-headers(允许跨域请求的请求头)
-
服务端还可以通过
Access-Control-Max-Age
来设置一定时间内无须再进行预检请求,直接用之前的预检请求的协商结果即可。 -
预检请求头中不会携带cookie,正式请求会携带cookie和参数。跟简单请求一样,响应头也会增加同样字段。
-
一旦服务器通过了“预检”请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样。
-
6.9.6.4 如何避免options 请求
-
使用代理,避开跨域
- Nginx反代理解决跨域问题
- Nginx中在响应中添加如下Header
location / { add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,POST' always; add_header 'Access-Control-Allow-Headers' '*'; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 200; } }
- Access-Control-Max-Age,用来指定本次预检请求的有效期,单位为秒。
- 上面配置中,有效期是10小时(36000秒),在此期间,不用发出另一条预检请求
- Nginx反代理解决跨域问题
-
将复杂请求更改为简单请求
-
不使用自定义Header
-
如果上面的中有一条我们没法避免就只能设置认证的生效时间了
Access-Control-Max-Age
。
6.9.6.5 options 的作用
- 获取服务器支持的HTTP请求方式,也是黑客经常使用的方法
- 检查服务器的性能,例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。
6.9.7 connect 请求
6.9.7.1 connect 请求的作用
- CONNECT请求是HTTP协议中的一种特殊请求方法
- 主要用于建立TCP / IP隧道连接。它允许客户端通过代理服务器与目标服务器建立一条直接的TCP连接,用于传输非HTTP协议的数据。
- 通过简单的隧道更改请求连接,通常实使用解码的HTTP代理来进行SSL编码的通信(HTTPS)。
- 实际上就是将服务器作为代理,让服务器代替用户去访问其他网页(说白了,就是翻墙),之后将数据返回给用户。
6.9.7.2 connect 请求的结构
-
connect请求格式: 请求行 +请求头 +请求体
-
请求行
CONNECT <host>:<port> HTTP/1.1
<host>
表示目标服务器的主机名或IP地址,<port>
表示目标服务器的端口号。
-
请求头
- 请求头包含的是
与请求相关的内容
,常见的请求 字段有Host:
指定目标服务器的主机名或IP地址和端口号。Proxy-Authorization:
用于在代理服务器上进行身份验证的凭证。一般就是开发中的Token
- 请求头包含的是
-
请求体: connect请求目的 在于建立连接,无请求体(无上行报文)
6.9.7.3 connect 请求的用途
-
代理服务器的建立
- CONNECT请求允许客户端通过代理服务器与目标服务器建立直接的TCP连接,从而实现代理服务器的建立。
- 基本的connect 请求代码
CONNECT example.com:443 HTTP/1.1 Host: example.com:443 Proxy-Authorization: Basic base64(username:password)
-
HTTPS的代理转发
- CONNECT请求在代理服务器上被用于转发HTTPS请求。当客户端发送CONNECT请求到代理服务器时,代理服务器会建立与目标服务器的SSL/TLS连接,并将客户端发送的加密数据直接转发给目标服务器。
- https 代理转发示例
CONNECT example.com:443 HTTP/1.1 Host: example.com:443 Proxy-Authorization: Basic base64(username:password) <encrypted data>
-
WebSocket的代理转发
- CONNECT请求也可以用于代理服务器转发WebSocket请求。当客户端发送CONNECT请求到代理服务器时,代理服务器会建立与目标服务器的WebSocket连接,并将客户端发送的WebSocket数据直接转发给目标服务器。
- websocket 代理转发示例
CONNECT example.com:80 HTTP/1.1 Host: example.com:80 Proxy-Authorization: Basic base64(username:password) <WebSocket data>
6.9.8 head请求
6.9.8.1 定义
head请求与get请求类似,但不返回实际的响应主体。它主要用于获取资源的元数据,检查资源是否存在以及验证资源是否被修改。
6.9.8.2 head请求结构
-
结构:请求行 +请求头 +请求体
-
请求行 head + 请求地址 + 协议
HEAD /path/to/resource HTTP/1.1
-
请求头 Host: + 目标服务器地址
Host: example.com
-
无请求体
6.9.8.3 head 请求的作用
- 获取资源的元信息,例如文件的大小、修改时间等。这对于某些场景下只需要了解资源的基本信息而不需要下载实际内容的情况非常有用。
- 检查超链接的有效性;如果服务器返回404 Not Found状态码,则表示资源不存在;如果返回200 OK状态码,则表示资源存在。
- 检查网页是否被修改;可以获取资源的ETag或Last-Modified头信息,用于验证资源是否被修改。如果客户端拥有先前获取的ETag或Last-Modified值,并发送到服务器进行比较,服务器可以
返回304 Not Modified状态码,表示资源未被修改
。 - 当前实体与缓存实体的阈(yu)值不同时(可通过
Content-Length
、Content-MD5
、ETag
或Last-Modified
的变化来表明),则缓存视为过期 - 只请求资源的首部;节省带宽和服务器资源
- head 请求的响应头可以被缓存
- 多用于自动搜索机器人获取网页的标志信息,获取rss种子信息,或者传递安全认证信息等
6.9.9 trace请求
6.9.9.1 定义
当客户端发送TRACE请求时,服务器将原始请求报文作为响应返回给客户端,用于检查或调试请求的传输过程。
6.9.9.2 trace 请求作用
- 调试: 通过回显请求报文,开发人员可以查看请求在传输过程中是否被修改,以及服务器对请求的处理过程。
- 诊断: TRACE请求可以用于诊断网络问题,例如检查请求是否被正确地转发到目标服务器。
- 测试: 开发人员可以利用TRACE请求测试API的可用性和正确性。
6.9.9.3 trace 请求应用场景
- API测试和调试: 开发人员可以使用TRACE请求来测试和调试API的请求和响应,以确保API的正确性和可用性。
- 请求追踪: TRACE请求可用于跟踪请求的传输过程,帮助开发人员诊断和解决网络问题。
- 安全审计: TRACE请求可以用于安全审计,帮助检查请求是否被篡改或劫持。
6.9.9.4 trace 请求示例
TRACE /path HTTP/1.1
Host: example.com
6.9.10 标准http请求 和 非标准http请求的区别
原文链接 解密 TLS/SSL 连接 > 处理 CONNECT 请求处理
6.9.10.1 http 和 https的 connect 请求
- 两者的不同
- https 处理请求期间,应用的阻止 和 重定向的结果与 http 处理相同请求 的结果不一样。
- https 协议 用户将不会看到阻止页面,不会被重定向到指定的 URL,而是连接被终止;
- http 可以看到阻止页面,或者重定向到指定url
- 造成不同的原因
- 为了建立加密的 HTTPS 连接,用户的计算机请求从代理服务器连接到 Web 服务器使用包含 CONNECT 方法的 HTTP 消息(以下简称“CONNECT 请求”)。
- 代理服务器处理 CONNECT 请求并回复这些请求的能力在 HTTP 协议级别上是有限的。
- 代理服务器可以通知用户连接成功,也可以终止连接。
- 解决 https 阻止和重定向被终止的问题
启用 TLS/SSL 连接的解密
且将 CONNECT 方法添加到排除项中
为其创建旁路规则
- 注意事项
- 如果没有允许 CONNECT 请求的流量处理规则,连接将被终止;
- 允许 CONNECT 请求可能会降低公司 IT 基础架构的安全性
- 建议仅在显示阻止页面或重定向对其关键的流量(请求)处理规则中将 CONNECT 方法添加到排除项。
6.9.10.2 标准 http 请求的过程
-
概述:大部分 HTTP 方法(例如,GET, POST, DELETE, HEAD, OPTIONS, PATCH, PUT 和TRACE)是用来在客户端(用户计算机)和存储 所请求 web 资源的 web 服务器之间交换消息。Kaspersky Web Traffic Security 可以扫描此类 HTTP 消息和将所有可用操作应用到这些消息。下图说明了 Kaspersky Web Traffic Security 中的 HTTP 消息处理原则。
-
图中的数字对应于标准 HTTP 消息处理的以下阶段
- 用户请求访问网络资源。该请求将被中继给代理服务器。
- 应用程序检查请求的 web 资源是否满足访问规则的条件。
- 如果访问规则的应用程序导致 阻止 操作,则用户将看到阻止页面。如果应用 重定向 操作,则用户将重定向到指定的 URL。
- 如果访问规则的应用程序导致 允许 操作,则应用程序将继续使用保护规则或默认保护策略 扫描流量。如果未检测到任何威胁,则用户请求将重定向到 web 服务器。
- 保护模块还会扫描从 web 服务器接收到的响应,以查找病毒或其他威胁。当检测到威胁时,应用程序会阻止流量。如果未检测到任何威胁,应用程序会将响应从 web 服务器中继到用户计算机。
- 在未经授权的访问尝试期间,入侵者可能会拦截数据,因为流量以未加密的形式进行传输。
6.9.10.3 处理连接请求过程
- 概述:当尝试通过 HTTPS 协议访问 web 资源时,用户计算机会向代理服务器发送 CONNECT 请求,请求连接到 web 服务器。由于加密设置和安全证书的交换,在用户计算机和 web 服务器之间通过 TLS 协议建立了隧道安全连接。在隧道内,客户端和 web 服务器使用标准 HTTP 方法(GET, POST 等)交换消息。默认情况下,代理服务器不能分析加密连接的内容或干预隧道内的消息交换。下图说明了处理默认加密连接的机制。
- 图中的数字对应于默认加密连接处理的以下阶段:
- 用户计算机向代理服务器发送 CONNECT 请求,请求使用 web 服务器进行加密的数据通道。
- 应用程序检查请求的 web 资源是否满足访问规则的条件。
- 如果规则的应用导致 阻止 或 重定向 操作,则连接将终止。用户将不会看到阻止页面,不会被重定向到指定的 URL。
- 如果访问规则的应用导致 允许 操作,则应用程序将发送一个 CONNECT 请求,供保护模块进一步处理。
- 在保护模块成功扫描 CONNECT 请求后,代理服务器在用户计算机和 web 服务器之间建立加密的数据通道。
- 用户的计算机与加密数据通道内的 web 服务器交换标准 HTTP 消息。代理服务器无法访问此类邮件,并且保护模块会对其进行扫描,因为传输的数据是加密的。
- 来自 web 服务器的响应也会直接中继到用户计算机,而不会被保护模块固定。这降低了企业 IT 基础架构的保护级别,因为用户计算机可以接收包含威胁的流量。
- 在未经授权的访问尝试期间,入侵者无法拦截数据,因为流量是在加密通道内传输的。## 七 HTML、CSS 相关内容
6.9.10.4 启用 TLS/SSL 的加密连接过程
- 要使应用程序能够使用保护模块扫描在加密数据通道内传输的流量,您需要配置 TLS/SSL 连接的解密。下图说明了通过启用 TLS/SSL 连接解密来处理加密连接的机制。
- 图中的数字对应于启用 TLS/SSL 连接解密的加密连接处理的以下阶段:
- 用户计算机向代理服务器发送 CONNECT 请求,请求使用 web 服务器进行加密的数据通道。
- 应用程序检查请求的 web 资源是否满足访问规则的条件。
- 如果访问规则的应用程序导致 阻止 或 重定向 操作,则连接将终止。用户将不会看到阻止页面,不会被重定向到指定的 URL。
- 如果访问规则的应用导致 允许 操作,则应用程序将发送一个 CONNECT 请求,供保护模块进一步处理。
- 保护模块成功扫描 CONNECT 请求后,则在用户的计算机和代理服务器之间以及代理服务器和 Web 服务器之间将被建立加密的数据通道。
- 用户计算机与加密数据通道内的 web 服务器交换标准 HTTP 请求。应用程序被授予对正在传输的所有数据的访问权限,并可以对其应用保护规则。
- 应用程序检查请求的 web 资源是否满足访问规则的条件。
- 如果访问规则的应用程序导致 阻止 操作,则用户将看到阻止页面。如果应用 重定向 操作,则用户将重定向到指定的 URL。
- 如果访问规则的应用程序导致 允许 操作,则应用程序将继续使用保护规则或默认保护策略扫描流量。如果未检测到任何威胁,则用户请求将重定向到 web 服务器。
- 保护模块还会扫描从 web 服务器接收到的响应,以查找病毒或其他威胁。当检测到威胁时,应用程序会阻止流量。如果未检测到任何威胁,应用程序将通过加密数据通道将响应从 web 服务器中继到用户计算机。
- 在未经授权的访问尝试期间,入侵者无法拦截数据,因为流量是在加密的数据通道内传输的。
七、HTML 和 CSS
7.1 页面重绘和回流
7.7.1 什么是重绘和回流
- 回流(reflow):也叫重排,指的是当渲染树中的节点信息发生了
大小、边距等问题,需要重新计算各节点和css具体的大小和位置
。需要走完整的渲染过程。 - 重绘(repaint):当节点的部分属性发生变化,但不影响布局,只需要重新计算节点在屏幕中的绝对位置并渲染的过程。比如:改变元素的背景颜色、字体颜色等操作。重绘少布局和分层
- 重绘不一定会引发回流,回流必然导致重绘。
- 重绘的执行效率比重排的执行效率高 - 1.2 什么操作引起重绘
7.7.2 修改以下属性会引起重绘操作
color
border-style
border-radius
text-decoration
box-shadow
outline
background
7.7.3 什么操作引起回流
7.7.3.1 改变元素的位置和大小操作
- 添加删除可见的DOM元素
- 元素尺寸改变
- 内容变化(如 input文本内容发送变化)
- 浏览器窗口改变。元素的大小和位置都是以窗口为参照的
- 设置style的属性值
- 激活css伪类,如:hover
- 获取布局的属性或者方法。浏览器对回流和重绘有一定的优化机制,就是浏览器会将回流放在一个队列中,经过一定时间或者操作达到了临界值,就会挨个执行。如果获取属性值,需要是最新的布局信息,浏览器就会强制清空队列(强制回流)。
7.7.3.2 css 相关(几何属性:布局、尺寸)
display
flex
position
float
left
right
top
bottom
width
height
margin
padding
border
font-size
text-align
overflow:有滚动条和无滚动条位置大小有所改变
vertical-align
line-height
7.2 获取布局的属性和方法
offsetTop
offsetLeft
offsetWidth
offsetHeight
scrollTop
scrollLeft
scrollWidth
scrollHeight
clientTop
clientLeft
clientWidth
clientHeight
getComputedStyle()
7.3 性能优化
7.3.1 样式合并修改
1. 将修改的样式用一个类名代替,动态添加删除类名
```javascript
<style>
.test{
padding:5px;
border:1px solid #000;
margin:5px;
}
</style>
<script>
let oDiv = document.getElementById("test")
oDiv.classList.add('test');
</script>
```
2. 使用style的cssText属性
```javascript
const oDiv = this.$refs.userName
// += 是在原来的元素上添加cssText的样式,原来的样式也保留
// ;padding 前添加一个分号是为了兼容IE,IE不能实现样式累加
oDiv.style.cssText += ';padding:5px; border:1px solid #000; margin:5px;';
```
7.3.2 批量操作DOM
思路:核心是使元素脱离标准流,操作结束再放回标准流中。(不在标准流中的元素修改不会触发回流)
7.3.2.1 隐藏元素
原因:在隐藏ul和显示ul的时候,触发了两次回流,给ul添加每个li的时候没有触发回流
let oUl = document.getElementById("test")
oUl.style.display = 'none';
for(var i=0;i<data.length;i++){
var oLi = document.createElement("li");
oLi.innerText = data[i].name;
oUl.appendChild(oLi);
}
oUl.style.display = 'block';
7.3.2.2 使用文档碎片
思路:创建文档碎片,将所有li先放在文档碎片中,等都放进去以后,再将文档碎片放在ul中
let oUl = document.getElementById("test")
// 创建文档碎片
let fragment = document.createDocumentFragment();
for(var i=0;i<data.length;i++){
var oLi = document.createElement("li");
oLi.innerText = data[i].name;
fragment.appendChild(oLi);
}
oUl.appendChild(fragment);
7.3.2.3 拷贝节点
思路:将ul拷贝一份,将所有li放在拷贝中,等都放进去以后,使用拷贝替换掉ul
let oUl = document.getElementById("test")
// 拷贝节点
let newUL = oUl.cloneNode(true);
for(var i=0;i<data.length;i++){
var oLi = document.createElement("li");
oLi.innerText = data[i].name;
newUL.appendChild(oLi);
}
oUl.parentElement.replaceChild(newUl, oUl);
7.3.2.4 其他
- 避免设置多层的内联样式。样式层级过多会影响重绘重排效率。
- 避免使用table布局。很小的变动会引起table重排。可用ul li span等标签生成table表格
- 对于复杂的动画,尽量将元素设置为绝对定位。操作元素的定位属性可以只使这一个元素回流,如果不是,容易引起其父元素和子元素的回流。