迷茫了,面前端就一直在笔试面试然后被刷,前天试了一家测试(划重点,就大二上过一小小小段时间的测试课,知识点都不记得了)题目全靠蒙,结果懵懵的过了??!不是外包,就很突然,可能是因为后面去了也会再培训吧。我虽然很想逃离这里,但是不是这样逃离的啊啊啊啊啊啊!给个前端走到最后的机会吧我想回长沙TT
从url的输入到页面展示
超级详细!我这是根据这篇文章拿的摘抄 输入url地址 在浏览器中输入网址的时候,浏览器就已经在智能的匹配可能的 url 了,会从历史记录,书签等地方,找到已经输入的字符串可能对应的 url,然后给出智能提示,让你可以补全url地址。 对于 google的chrome 的浏览器,甚至会直接从缓存中把网页展示出来,就是说,你还没有按下 enter,页面就出来了。 应用层进行DNS解析 应用层生成HTTP请求报文 应用层生成针对目标WEB服务器的HTTP请求报文,HTTP请求报文包括起始行、首部(请求头(Request Header))和主体(请求正文)部分。 传输层建立TCP连接 三次握手 四次挥手 (传输层传输协议分为UDP和TCP两种 UDP是无连接的协议,而TCP是可靠的有连接的协议,主要表现在:接收方会对收到的数据进行确认、发送方会重传接收方未确认的数据、接收方会将接收到数据按正确的顺序重新排序,并删除重复的数据、提供了控制拥挤的机制) 握手成功后,浏览器向服务器发送http请求,请求数据包。 服务器处理收到的请求,将数据返回至浏览器 服务器返回一个 HTTP 响应 HTTP响应报文也是由三部分组成: 状态码, 响应报头和响应报文。 浏览器渲染 1)、使用parse模块解析HTML、CSS、Javascript资源 2)、构建DOM树、Render树及RenderLayer树 3)、布局和渲染 4)、硬件加速 开启硬件渲染,即合成加速,会为需要单独绘制的每一层创建一个GraphicsLayer
硬件渲染是指网页各层的合成是通过GPU完成的,它采用分块渲染的策略,分块渲染是指:网页内容被一组Tile覆盖,每块Tile对应一个独立的后端存储,当网页内容更新时,只更新内容有变化的Tile。分块策略可以做到局部更新,渲染效率更高
四次挥手
第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN WAIT1状态。 第二次挥手:服务端收到FIN后,会发送ACK报文,并且把客户端的序列号值+1作为ACK报文的序列号,表明已经收到客户端报文,此时服务端处于CLOSE_WAIT状态。 第三次挥手:如果服务端也想断开连接,和客户端第一次挥手一样,发给FIN报文,且指定一个序列号。此时服务端处于LAST_ACK状态。 第四次挥手:客户端收到FIN之后,一样发送一个ACK报文作为应答,且把服务端的序列号值+1作为自己ACK报文的序列号,此时客户端处于TIME_WAIT状态。需要过一阵子以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文之后,就处于关闭连接了,处于CLOSED状态。
cookie与session
cookie: 是保存在客户端的,一般由后端设置值,可以设置过期时间,存储大小只有4k。一般用来保存用户的信息,在http下cookie是明文传输的,比较不安全。
cookie属性有: http-only:不能被客户端更改访问,防止XSS攻击(保证cookie安全性的操作) secure:只允许在https下传输。 max-age:cookie生成后失效的秒数。 expire:cookie最长的有效时间,如果不设置则cookie生命期和会话期相同。
session: session是保存在服务端的,其运行依赖sessionId,而sessionId又保存在cookie中,所以如果禁用cookie,session也是不能用的,除非吧sessionId保存在URL中。 session一般用来跟踪用户状态。 session的安全性更高,保存在服务端,一般为了服务端性能更加,会考虑部分信息保存在cookie中。
localStorage与sessionStorage
localStorage: 关闭浏览器后数据依然保留,除非手动清除,否则一直在。 作用域:相同浏览器的不同标签在同源的情况下可以共享localStorage。
sessionStorage: 关闭浏览器或者标签后立即失效。 作用域:只在当前标签可用,当前标签的iframe中且同源可以共享。
判断浏览器环境还是node
通过判断 Global 对象是否为 window ,如果不为window ,当前脚本没有运行在浏览器中
this === window ? console.log('browser') : console.log('node');
浏览器多个标签页通讯
我也是第一次了解到 属于懵 1、cookie+setInterval 想要在多个窗口中通信,通信的内容一定不能放在window对象中,因为window是当前对象窗口的作用域,里面的内容只属于当前窗口。有一种方式可以放在cookie中,cookie是浏览器的本地存储机制,和窗口无关,存在于硬盘上都可以读取。 缺点: cookie空间有限,浏览器在每一个域名下最多能设置30-50个cookie,容量最多为4k左右。 每次HTTP请求才会把当前域的cookie发送到服务器上,包括只在本地才用到的而服务器不用的,浪费宽带。 serInterval频率设置过大会影响浏览器的性能,过小会影响时效性。
2、localStorage localStorage比cookie好在它setItem存东西时会自动触发整改浏览器是storage事件,除了当前页面之外,所有打开的标签窗口都会受影响。 缺点: localStorage是h5的属性,高版本的浏览器才会支持,而且不同的浏览器localStorage大小限制不统一。 localStorage只能监听非己页面的数据变化。 优点:解决了cookie容量小和时效性的问题。
webSocket方式 webSocket需要用到服务端,send.html发送消息到WebSocketServer,WebSocketServer再实时把消息发给receive.html,其实这就是实时通信的原理(微信、qq、淘宝旺旺等)
新建webSocket文件夹,在webSocket目录下打开终端,运行npm init初始化一个简单的node项目(因为需要引入ws包),一直按回车到结束就初始了一个简单的node项目。再安装ws包,运行npm i -save ws,在webSocket目录下新建sever.js、send.html、receive.html文件
缺点: 它需要服务端的支持才能完成任务。如果socket数据量比较大的话,会严重消耗服务器的资源。 必须要在服务端项目中写服务端监听程序才能支持。 优点: 使用简单(客户端简单,服务端苦逼了),功能灵活、强大,如果部署WebSocket服务器,可以实现很多实时的功能。
4、SharedWorker方式 WebWorker的升级版,WebWorker只能在一个窗口内使用,而现在我们需求是多个窗口之间通信,就要用SharedWorker了。 SharedWorker原理和WebWorker几乎是一样的,只不过SharedWorker可以跨多个页面使用。 SharedWorker也是纯客户端的,没有服务端的参与。 SharedWorker在客户端有一个自己维护的对象worker.js,消息存储在worker.js中的data中。 SharedWorker不如localStorage的是接收消息不是自动的,也要用定时器实时从worker.js中获取消息。
跨域问题为什么存在?怎么解决?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。 跨域,是指浏览器不能执行其他网站的脚本。是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
JSONP通过同源策略涉及不到的"漏洞",也就是像img中的src,link标签的href,script的src都没有被同源策略限制到。JSONP只能get请求
只能跨一级域名相同的域(www.qq.om和www.id.qq.com , 二者都有qq.com)
因为hash传值只能单向传输,所有可以通过一个中间网页,a若想与b进行通信,可以通过一个与a同源的c作为中间网页,a传给b,b传给c,c再传回a
具体做法:在a中放一个回调函数,方便c回调。放一个iframe标签,随后传值
在b中监听哈希值改变,一旦改变,把a要接收的值传给c
在c中监听哈希值改变,一旦改变,调用a中的回调函数
Access利用window.name不会改变(而且很大)来获取数据, a要获取b的数据,b中把数据转为json格式放到window.name中
a窗口向b窗口发送数据,先把data转为json格式,在发送。提前设置好messge监听 b窗口进行message监听,监听到了以同样的方式返回数据, a窗口监听到message,在进行一系列操作
通过自定义请求头来让服务器和浏览器进行沟通 有简单请求和非简单请求 满足以下条件,就是简单请求 请求方法是HEAD、POST、GET 请求头只有Accept、AcceptLanguage、ContentType、ContentLanguage、Last-Event-Id 简单请求,浏览器自动添加一个Origin字段 同时后端需要设置的请求头 Access-Control-Allow-Origin --必须 Access-Control-Expose-Headers
nginx模拟一个虚拟服务器,因为服务器与服务器之间是不存在跨域的, 发送数据时 ,客户端->nginx->服务端 返回数据时,服务端->nginx->客户端
jsonp的实现以及优缺点
jsonp的原理:json+padding,动态创建script标签,利用script标签的src属性可以获取任何域下的js脚本,通过这个特性(也可以说漏洞),服务器端不在返货json格式,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域.
优点:
- 完美解决在测试或者开发中获取不同域下的数据,用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。简单来说数据的格式没有发生很大变化。
缺点:
- jsonp只支持get请求而不支持post请求,也即是说如果想传给后台一个json格式的数据,此时问题就来了,浏览器会报一个http状态码415错误,告诉你请求格式不正确。如果都用参数的形式拼接在url后面的话不太现实,后台取值也会显得繁琐。
- 在登录模块中需要用到session来判断当前用户的登录状态,这时候由于是跨域的原因,前后台的取到的session是不一样的,那么就不能就行session来判断。
- jsonp存在安全性问题
csrf的攻击以及防范
CSRF:跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。 简单理解:冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。
CSRF攻击形式: 1、用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A; 2、在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A; 3、用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B; 4、网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A; 5、浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
CSRF防御方法:
- (1)验证 HTTP Referer 字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,验证其 Referer 值,如果是以网站安全开头的域名,则说明该请求是来自网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。 但是 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。 - (2)在请求地址中添加 token 并验证
token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。 但是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。 - (3)在 HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。 但是XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。
HTTP状态码
状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接受。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。 平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500。
- 200 OK 表示客户端请求成功
- 204 No Content 成功,但不返回任何实体的主体部分
- 206 Partial Content 成功执行了一个范围(Range)请求
- 301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL
- 302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源
- 303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源
- 304 Not Modified 服务器内容没有更新,可以直接读取浏览器缓存
- 400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
- 401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
- 403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
- 404 Not Found 请求的资源不存在,例如,输入了错误的URL
- 500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
- 503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常
浏览器遇到script怎样?怎么解决
在HTML文档中编写JavaScript代码时,要放在标签内,但是在使用script标签嵌入JavaScript代码时,记住不要在代码中的任何地方出现 “”的字符串,例如:
<script type="text/javascript>"
function sayScript() {
alert("</script>");
}
</script>
按照解析代码的规则,当浏览器遇到字符串”</script>” 时,它会认为这是结束的
</script>标签,可以通过转移字符”\”解决这个问题,如下:
<script type="text/javascript>"
function sayScript() {
alert("<\/script>");
}
</script>
这样浏览器就不会解析错误了。
隐藏页面元素
(1)使用 display:none;隐藏元素,渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
(2)使用 visibility:hidden;隐藏元素。元素在页面中仍占据空间,但是不会响应绑定的监听事件。
(3)使用 opacity:0;将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
(4)通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
(5)通过 z-index 负值,来使其他元素遮盖住该元素,以此来实现隐藏。
(6)通过 clip/clip-path 元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
(7)通过 transform:scale(0,0)来将元素缩放为 0,以此来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
组件间数据传递
父子组件通信: 在父组件data里定义一个要通信的数据
data(){
return {
parentStr:'这是父组件的数据',
num:1,
}
}
<son-component :xxx = 'parentStr' :num = 'num'></son-component>
xxx是一个名称 ''里面是值
然后子组件通过props属性,在子组件中接收父组件传过来的值
子组件里接收数据
props:['xxx','num'],
也可以写成对象格式
props:{
xxx:String,
num:Number,
}
{{xxx}}{{num}}
子父组件通信: 在子组件data里定义一个要通信的数据,给子组件定义一个按钮,通过自定义事件.$emit
子组件{{str}}
<button @click='btn'>按钮</button>
data(){
return {
str:'这是子组件内容',
}
},
methods:{
btn(){
this.$emit('changeStr',this.str),
}
}
父组件定义@changeStr,两者需要一致, 通过方法收到来自子组件的数据
<child @changeStr='fn'></child>
{{change}}
data(){
return {
change:'',
}
},
methods:{
fn(val){
this.change = val;
}
}
兄弟组件通信: AB兄弟组件,bus中转
const EventBus = new Vue();
A兄弟组件(自定义组件)
AAA
<button @click='btn'>A按钮</button>
data(){
return {
Astr:'这是A组件数据',
}
},
methods:{
btn(){
EventBus.$emit('changeStr',this.Astr),
}
}
B兄弟组件接收数据
<div>{{Bstr}}</div>
created() {
EventBus.$on('changeStr', (data) => {
console.log('来自A的数据:', data);
this.Bstr= data;
});
},
|