1.浏览器缓存
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,
若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),
协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,
重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
强缓存 1.Expires Expires: Wed, 22 Oct 2018 08:41:00 GMT
表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期。(受限于本地时间,如果修改了本地时间,可能会造成缓存失效)
2.Cache-Control Cache-Control:max-age=300(超过300m,优先级高于expires)
协商缓存 协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求协商缓存生效,返回304和Not Modified
1. Last-Modified(以秒计时,本地打开缓存文件,不能命中缓存)
2. ETag(当前资源文件的一个唯一标识(由服务器生成),要优于Last-Modified)
实际应用 不常变化的资源 (Cache-Control: max-age=31536000) 静态组件(Expires不过期)
频繁变动的资源 需要使用Cache-Control: no-cache 使浏览器每次都请求服务器, 配合 ETag 或者 Last-Modified 来验证资源是否生效
2.安全策略
1、跨站脚本攻击(XSS)
一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而产生了新的语义
XSS的防御
1、HttpOnly (浏览器禁止页面的Javascript访问带有HttpOnly属性的cookie)
2. 输入检查 输出检查(XSS Filter)转义字符,对于用户的输入应该是永远不信任的。最普遍的做法就是转义输 入输出的内容,对于引号、尖括号、斜杠进行转义
3、CSP CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行
1.设置 HTTP Header 中的 Content-Security-Policy
2.设置 meta 标签的方式 <meta http-equiv="Content-Security-Policy">
2、CSRF(跨站点请求伪造)
CSRF攻击是攻击者利用用户身份操作用户账户的一种攻击方式,攻击者构造出一个后端请求地址
1、验证码
2、由于Token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击
3、不让第三方网站访问到用户 Cookie
5.url请求到渲染,中间优化
1. 用户输入URL地址
2. 浏览器解析URL解析出主机名
3. 浏览器将主机名转换成服务器ip地址(浏览器先查找本地DNS缓存列表 没有的话 再向浏览器默认的DNS服务器 发送查询请求 同时缓存)
4. 浏览器将端口号从URL中解析出来
5. 浏览器建立一条与目标Web服务器的TCP连接(三次握手)
6. 服务端返回html
7.浏览器渲染(渲染进程是多线程的,GUI渲染线程,js引擎线程,事件触发线程,定时触发器线程,异步http请求线程)
- DOM树构建
- CSSOM树构建
- RenderObject树构建
- 布局
- 绘制
**使用DNS预解析**
DNS 在 一次请求中,DNS解析可以占到请求时间的三分之一左右(这点有待验证),所以如果可以缩短DNS解析时间,就可以加快页面的打开速度。 rel="dns-prefetch" 用以DNS预解析
减少DNS查找(例如原来有5个img server,分别为img1.xxx.com至img5.xxx.com,则现在可以减少到3个)
**请求**
1.尽量减少HTTP请求 (CSS sprites将背景图片合并成一个文件)多个接口合并
2.避免空src或者是href值 <a href="#"></a>
空的src和href都会导致多余的HTTP请求,虽然不影响加载时间,但是会对服务器产生不必要的流量和压力。浏览器仍然会向服务器发起一个 HTTP 请求
3.**避免重定向**3xx是重定向相关的HTTP响应代码,避免404浏览器找不到资源的情况发生
4.**使Ajax可缓存**我们可能希望`GET`请求不被缓存$.ajaxSetup({ cache: false });
5.减小cookie大小 减小cookie的大小,因为在发请求时浏览器会将cookie信息发送到server端,所以应该只在cookie中存必要的信息且越长度越小越好
6.利用浏览器缓存
**浏览器渲染**
1.压缩资源(webpack)
2.CSS放在顶部,JS放在底部`defer`和 `async` 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
3.重排reflow与重绘repaint
只触发重绘不触发重排的一些CSS属性:js尽量少访问dom节点和css 属性,不要通过父级来改变子元素样式,最好 直接改变子元素样式,改变子元素样式尽可能不要影响父元素和兄弟元素的大小和尺寸,尽量通过class来设计元素 样式,切忌用style 多次操作单个属性
#### 代码部分
for循环、迭代、同步、重定向、阻塞请求,未删除重复、无用的代码,未加入Async异步机制
6.水平垂直居中,两边固定中间自适应布局
position transform
position: absolute;left: 50%;top: 50%;transform: translate(-50%,-50%);
flex布局
display: flex;//flex布局 justify-content: center;//使子项目水平居中 align-items: center;//使子项目垂直居中
table-cell布局
.wp{display: table-cell;text-align: center;vertical-align: middle;}.box{display: inline-block;}
absolute + calc
.wp { position: relative;}.box { position: absolute;; top: calc(50% -50px); left: calc(50% -50px);}
两边固定中间自适应布局
1).绝对定位法
2).使用自身浮动法
3、css3新特性,使用flex
4.. 双飞翼布局
7.跨域,如何跨域,跨域图片如何处理
域名、协议、端口有一个不同就不是同源,三者均相同,这两个网站才是同源
浏览器会对上面提到的跨域请求作出限制。浏览器之所以要对跨域请求作出限制,是出于安全方面的考虑,因为跨域请求有可能被不法分子利用来发动 CSRF攻击。
JSONP
JSONP 本质上是利用 <script><img><iframe> 等标签不受同源策略限制,可以从不同域加载并执行资源的特性,来实现数据跨域传输。
优缺点:
JSONP 的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行。
JSONP 的缺点是:它只支持 GET 请求,而不支持 POST 请求等其他类型的 HTTP 请求
CORS
跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源
与 JSONP 的比较
JSONP 只能实现 GET 请求,而 CORS 支持所有类型的 HTTP 请求
使用 CORS ,开发者可以是使用普通的 XMLHttpRequest 发起请求和获取数据,比起 JSONP 有更好的错误处理
虽然绝大多数现代的浏览器都已经支持 CORS,但是 CORS 的兼容性比不上 JSONP,一些比较老的浏览器只支持 JSONP
8.vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
主要包括以下几个模块:
State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。
state
通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过this.$store 访问到 this.$store.state.count
mapState 辅助函数
import{mapState}from'vuex'
computed:mapState([// 映射 this.count 为 store.state.count'count'])
Getters
我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
getters:{doneTodos:state=>{returnstate.todos.filter(todo=>todo.done)}}
mapGetters 辅助函数
import{mapGetters}from'vuex'
export default{// ...computed:{// 使用对象展开运算符将 getter 混入 computed 对象中...mapGetters(['doneTodosCount','anotherGetter',// ...])}}
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
mutations:{increment(state){// 变更状态state.count++}
store.commit('increment')
Action
store.dispatch('increment')
9.vue nextick与宏任务微任务浏览器循环
vue的nextTick方法的实现原理了,总结一下就是:
vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
microtask因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
因为兼容性问题,vue不得不做了microtask向macrotask的降级方案
任务队列又分为macro-task(宏任务)与micro-task(微任务),在最新标准中,它们被分别称为task与jobs。
macro-task大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task大概包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
其中,nextTick队列会比Promie先执行。nextTick中的可执行任务执行完毕之后,才会开始执行Promise队列中的任务。
当所有可执行的微任务执行完毕之后,这一轮循环就表示结束了。下一轮循环继续从宏任务队列开始执行。
这个时候,script已经执行完毕,所以就从setTimeout队列开始执行。
10.vue 原理以及diff算法和虚拟dom
输入框内容变化时,Data 中的数据同步变化。即 View => Data 的变化。
Data 中的数据变化时,文本节点的内容同步变化。即 Data => View 的变化。
其中,View 变化更新 Data ,可以通过事件监听的方式来实现,所以 Vue 的数据双向绑定的工作主要是如何根据 Data 变化更新 View。
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
虚拟 DOM 的实现原理主要包括以下 3 部分:
用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
diff 算法 — 比较两棵虚拟 DOM 树的差异;
pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
优点:
保证性能下限:框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
无需手动操作 DOM:我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
diff算法(一哈哈学不完)
11proxy与defineproperty
利用Proxy或Object.defineProperty生成的Observer针对对象/对象的属性进行"劫持",在属性发生变化后通知订阅者
Object.defineProperty() 只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持我们就能知道 Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用 Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。
Proxy 的优势如下:
Proxy 可以直接监听对象而非属性;
Proxy 可以直接监听数组的变化;
Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
Object.defineProperty 的优势如下:
兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。
12.项目中用的哪些模式(一哈哈学不完)
13.纯函数
如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。
14.vue-router 路由模式有几种?
hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
history.pushState() 和 history.repalceState()。前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示: