全系统学习web前端(一)关于http/html

本文章整理其他人处,如有侵权,联系我删除。

关于http与https

http是超文本传输协议,从www服务器传送超文本到本地浏览器的传输协议,它可以使得浏览器更加高效,使得网络传输减少。

https是以安全为目标的HTTP通道,安全版的http,加入ssl层,https的安全基础是ssl,因此加密的详细内容就需要ssl。

https和http的区别

http传输的数据未被加密,https是协议是由ssl和http构建的可进行加密传输和身份认证的网络协议,比http协议的安全性更高。

①https协议需要ca证书

②http明文,https加密

③http端口80,https端口443

https的工作原理

①客户端通过url访问服务器,要求web服务器创建ssl链接。

②web服务器收到请求之后,就将网站的证书(即公钥)返回给客户端。

③客户端和web服务器开始协商ssl链接的安全等级,即加密等级。

④客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话秘钥,传送给网站。

⑤web服务器通过自己的私钥解密出密钥。

⑥web服务器通过会话密钥加密与客户端之间的通信。

https的优点

①比http协议更安全,防止数据在传输过程中被窃取。

②https是现行架构下最安全的解决方案(今年2019)

https的缺点

①握手阶段比较费时间,会使页面加载时间延长50%

②https的缓存不如http高效,数据开销大。

③ssl证书需要钱。

④ssl证书需要绑定IP,不能再同一个ip上绑定多个域名。

tcp三次握手

第一次握手:S只可以确认 自己可以接受C发送的报文段第二次握手。

第二次握手:C可以确认 S收到了自己发送的报文段,并且可以确认自己可以接受S发送的报文段。

第三次握手:S可以确认C收到了自己发送的报文段。

TCP和UDP的区别

①TCP是面向连接的,UDP是无连接的,即发送数据前不需要建立连接。

②TCP提供可靠的服务。通过TCP连接传送的数据,无差错,不丢失,不重复,按序到达。UDP尽最大努力交付,即不保证可靠交付。并且因为TCP可靠,面向连接,不会丢失数据因此适合大数据量的交换。

③TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议)。

④TCP只能是1对1,UDP支持1对1,1对多。

⑤TCP的手部较大为20字节,而UDP只有8字节。

⑥TCP是面向连接的可靠性传输,而UDP是不可靠的。

webSocket的实现和应用

什么是webSocket

webSocket是h5中的协议,支持持久连续,http协议不支持持久性连接。Http1.0和Http1.1都不支持持久性的链接,Http1.1中的keep-alive,将多个http请求合并为1个。

webSocket是什么样的协议,具有什么优点

HTTP的生命周期通过Request来界定,Request 一个 Response。在Http1.0协议中,这次Http请求就结束了。在Http1.1中进行了改进。有一个connection: Keep-alive。在一个Http连接中,可以发送多个Request,接受多个Response。但是Http中一个Request只能对应有一个Response,这个Response是被动的,不能主动发起。

WebSocket是基于Http协议的,或者说借用了Http协议来完成一部分握手,在时握手阶段与Http是相同的。

基本请求如下:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

多了下面2个属性:

1

2

Upgrade:webSocket

Connection:Upgrade

告诉服务器发送的是websocket

1

2

3

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

Http请求的方式,HEAD方式

head:类似于 get请求,只不过返回的响应中没有具体的内容,用户获取报头。

options: 允许客户端查看服务器的性能,比如说服务器支持的请求方式等。

一个图片url访问后直接下载如何实现

设置response header中的disposition-type为attachment

web Quality(无障碍)

能够被残障人士使用的网站才能称得上一个易用的(易访问的)网站。

残障人士指的是那些带有残疾或者身体不健康的用户。

使用alt属性:

<img src="person.jpg"  alt="this is a person"/>

有时候浏览器会无法显示图像。具体的原因有:

用户关闭了图像显示

浏览器是不支持图形显示的迷你浏览器

浏览器是语音浏览器(供盲人和弱视人群使用)
如果您使用了alt 属性,那么浏览器至少可以显示或读出有关图像的描述。

什么是BOM,有什么BOM属性对象比较实用?

BOM:Browser Object Model,浏览器对象模型。

location对象

location.href 返回或设置当前文档的URL

location.search 返回URL中的字符串部分 返回包括?后面的部分 例如: http://www.......du.php?id=5&name=dreamdu 返回包括(?)后面的内容?id=5&name=dreamdu

location.hash 返回ULR#后面的内容,如果没有#,返回空

location.host 返回URL中的域名部分

location.hostname -- 返回URL中的主域名部分,例如dreamdu.com

location.pathname -- 返回URL的域名后的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/

location.port -- 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080

location.assign -- 设置当前文档的URL

location.replace() -- 设置当前文档的URL,并且在history对象的地址列表中移除这个URL location.replace(url);

location.reload() -- 重载当前页面

history 对象

history.go() -- 前进或后退指定的页面数 ( history.go(0) 和location.reload的区别是前者从缓存中读取数据,后者会从服务器端)

history.back() -- 后退一页

history.forward() -- 前进一页

Navigator对象

navigator.userAgent -- 返回用户代理头的字符串表示(即包括浏览器版本信息的字符串)

navigator.cookieEnabled -- 返回浏览器是否支持启用 cookie

关于H5中的 drag api

ondragstart 事件,主体为被拖动的元素,在开始拖放元素时触发。

drag 事件,主体为被拖动的元素,正在被拖动的时候触发。

dragend 事件,主体是被拖动元素,整个拖放操作结束触发。

dragenter 事件,主体为目标元素,在被拖放元素进入某元素时触发。

dragover 事件,主体是目标元素,被拖放元素在某元素内移动时触发。

dragleave 事件,主体是目标元素,在被拖动元素移除目标元素时触发。

drop 事件,主体是目标元素,在一个拖动过程中,释放鼠标时触发此事件。

以下是菜鸟网站上的

  • 在拖动目标上触发事件 (源元素):
    • ondragstart - 用户开始拖动元素时触发
    • ondrag - 元素正在拖动时触发
    • ondragend - 用户完成元素拖动后触发
  • 释放目标时触发的事件:
    • ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
    • ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
    • ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
    • ondrop - 在一个拖动过程中,释放鼠标键时触发此事件

关于http2.0

先补充一下,http和https的区别,就是https是基于ssl加密的http协议。

http2.0 提升访问速度(相比http1.0 请求资源所需时间更少,访问速度更快)

允许多路复用:多路复用允许同时通过单一的HTTP/2连接发送多重请求-响应信息。改善了http1.1中,浏览器客户端在同一时间、针对同一域名下的请求有一定的限制数量(连接数量)超过限制会被阻塞。

二进制分帧:Http2.0会将所有的传输信息分割成为更小的信息或者帧,并对他们进行二进制编码。

首部压缩

服务器端推送

关于400,401,403状态码

400状态码: 请求无效

产生的原因:前端提交数据的字段名称和字段类型与后台的实体没有保持一致。

前端提交到后台的数据应该是json字符串类型,但是前端没有将对象JSON.stringify转化成字符串。

解决:

对照字段的名称,保持一致性

将obj对象通过JSON.stringify实现序列化

401状态码:当前请求需要用户验证 即没有权限

403状态码:服务器得到请求,但是拒绝执行

fetch 发送2次请求的原因

fetch发送post请求的时候,总是发2次,第一次状态码是204

原因是,当用fetch的Post请求的时候,导致fetch 第一次发送了一个Options请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的数据。

Cookie、sessionStorage、localStorage的区别

共同点:都是保存在浏览器端,并且是同源的。

cookie:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下,存储的大小很小,只有4K左右(可以在浏览器和服务端来回传递,存储容量小,只有大约4K左右)

cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

sessionStorage: 仅在当前浏览器窗口关闭前有效,自然也就不可能持久保存。(本身就是一个会话过程,关闭浏览器后消失,session为一个会话,当页面不同即使是同一页面打开两次,也被视为一次会话)

localStorage: 始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;

localStorage在所有同源窗口中都是共享的,cookie也是在所有同源窗口中都是共享的。(同源窗口都会共享,并且不会失效,不管窗口或者浏览器关闭与否都会始终生效)

补充一下cookie的作用

保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面的时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。cookie还可以设置过期时间,当超过时间期限后,cookie就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见的选项有一个月、三个月、一年等。

跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气状况。如果每次都要选择所在地是繁琐的,当利用了cookie后就会显得很人性化了,系统能够记住上次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。

关于 web worker

Web Worker ,就是为Java Script 创造多线程环境,允许主线程创建 Worker线程,将一些任务分配给后者运行。在主线程运行的同时,Worker线程在后台运行,两者互不干扰。等到worker线程计算完成任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被Worker线程负担了,主线程(负责UI交互)就会很流畅,不会被阻塞或者拖慢。

worker线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了worker比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

再使用web worker之前有几个限制

①同源限制

分配给Worker线程运行的脚本文件,必须与主线程的脚本文件同源。

②DOM限制

woker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的DOM对象,也无法使用document, windows, parent 这些对象。但是workder 线程可以使用 navigator 和 location 对象。

③通信联系

worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

④脚本限制

worker 线程不能执行alert() 方法和 confirm() 方法 ,但可以使用XMLHttpRequest 对象发出AJAX请求。

⑤文件限制

worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

主线程的一些操作

主线程采用 new 命令,调用 Worker() 构造函数,新建一个Worker线程

var worker = New Worker('work.js') //需要运行的网络脚本添加在里面

Worker() 构造函数的参数是一个脚本文件,该文件就是Worker 线程所要执行的任务。由于Worker 不能读取本地文件,所以这个脚本必须来自网络。如果下载没有成功(比如404错误),Worker就会默默地失败。

然后,主线程调用 worker.postMessage() 方法,向Worker 发消息。

worker.postMessage('Hello World'); //主线程调用方法向worker线程发消息
worker.postMessage( { method:'echo', args:['works'] } )

worker.postMessage()方法的参数,就是主线程传给 Worker 的数据。它可以是各类数据类型,包括二进制数据。

接着,主线程通过 worker.onmessage 指定监听函数,接受子线程发来的消息。

worker.onmessage = function (event) {
    //下面的 data 属性可以获取 Worker 发来的数据
    console.log('Received message ' + event.data);
    doSomething();
}

function doSomething() {
    //执行任务
    worker.postMessage("这里面填写的是向发给worker线程的东西");
}

当Worker 完成任务之后,主线程可以把它关掉

worker.terminate();

Worker 线程的一些操作

Worker 线程内部需要有一个监听函数( addEventListener ),监听 message 事件

self.addEventListener('message', function (e) {
    self.postMessage('You said: ' + e.data);
},false)

上述代码中,self 代表子线程自身,即子线程的全局对象。因此,等同于下面两种写法。

// 写法一
this.addEventListener('message', function (e) {
  this.postMessage('You said: ' + e.data);
}, false);

// 写法二
addEventListener('message', function (e) {
  postMessage('You said: ' + e.data);
}, false);

除了使用 self.addEventListener() 指定监听函数,也可以使用 self.onmessage 指定。监听函数的参数是一个事件对象,它的 data 属性包含主线程发来的数据。 self.postMessage() 方法用来向主线程发送消息。

根据主线程发来的数据,Worker 线程可以调用不同的方法,下面是一个例子。

self.addEventListener('message', function (e) {
    var data = e.data;
    switch (data.cmd){
        case 'start':
            self.postMessage('WORKER STARTED: '+ data.msg);
            break;
        case 'stop':
            self.postMessage('WORKER STOPPED: ' + data.msg);
            self.close(); //Terminates the worker
            break;
        default:
            self.postMessage('Unknown command: '+ data.msg); 
    }
},false), 

 上述代码中,self.close() 用于在 Worker 内部关闭自身

Worker 加载脚本

Worker 内部如果要加载其他脚本,有一个专门的方法 importScripts()

该方法可以同时加载多个脚本

importScripts('script1.js', 'script2.js')

主线程对Worker 线程的错误处理

主线程可以监听 Worker 是否发生错误。如果发生错误,Worker 会触发主线程的 error 事件

worker.onerror(function (event) {
  console.log([
    'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
  ].join(''));
});

// 或者
worker.addEventListener('error', function (event) {
  // ...
});

Work 内部也可以监听 error 事件

关闭 Worker

使用完毕,为了节省系统资源,必须关闭 Worker

//主线程
worker.terminate();

//Worker 线程
self.close();

数据通信

主线程与 Worker之间的通信内容,可以是文本,也可以是对象。需要注意的是,这种通信是拷贝关系,即是传值而不是传地址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先讲通信内容串行化,然后把串行化后的字符串发给Worker,后者再将它还原。

主线程与Worker 之间也可以交换二进制数据,比如 File、Blob 、ArrayBuffer 等类型,也可以在线程之间发送。下面是一个例子。

// 主线程
var uInt8Array = new Uint8Array(new ArrayBuffer(10));
for ( var i = 0; i< uInt8Array.length; ++i){
    uInt8Array[i] = i * 2; //[0,2,4,6,8...]
}
worker.postMessage(uInt8Array);

//Worker 线程
self.onmessage = fuction (e) {
    var uInt8Array = e.data;
    postMessage('Inside worker.js:uInt8Array.toString() =' + uInt8Array.toString());
    postMessage('Inside worker.js:uInt8Array.byteLength =' + uInt8Array.byteLength);
}

但是,拷贝方式发送二进制数据,会造成性能问题。比如,主线程向Worker 发送一个 500MB 文件,默认情况下浏览器会生成了一个原文件的拷贝。为了解决这个问题,JavaScript 允许主线程把二进制数据直接转移给子线程,但是一旦转移,主线程就无法再使用这些二进制数了,这是为了防止出现多个线程同时修改数据的麻烦局面。这种转移数据的方法,叫做Transferable Objects。这使得主线程可以快速把数据交给Worker,对于影像处理、声音处理、3D运算等就非常方便了,不会产生性能负担。

如果要直接转移数据的控制权,就要使用下面的写法。

// Transferable Objects 格式

Worker.postMessage( arrayBuffer, [arrayBuffer] );

// 例子
var ab = new ArrayBuffer(1)
worker.postMessage(ab, [ab]);

同页面的Web Worker

通常情况下,Worker 载入的是一个单独的JavaScript 脚本文件,但是也可以载入与主线程在同一个网页的代码。

<!DOCTYPE html>
  <body>
    <script id="worker" type="app/worker">
      addEventListener('message', function () {
        postMessage('some message');
      }, false);
    </script>
  </body>
</html>

上面是一段嵌入网页的脚本,注意必须指定 <script> 标签的 type 属性是一个浏览器不认识的值,上例是 app/worker

然后,读取这一段嵌入页面的脚本,用 Worker 来处理

var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);

worker.onmessage = function (e) {
  // e.data === 'some message'
};

上面代码中,先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成URL,再让 Worker 加载这个URL。这个就做到了,主线程和 Worker 的代码都在同一个网页上面。

实例:Worker 线程完成轮询

有时,浏览器需要轮询服务器状态,以便第一时间得知状态改变。这个工作可以放在Worker 里面

function createWorker(f) {
    var blob = new Blob(['(' + f.toString() +')()']);
    var url = window.URL.createObjectURL(blob);
    var worker = new Worker(url);
    return worker;
}

var pollingWorker = createWorker(function (e) {
    var cache;
    
    function compare(new, old) { ... };
    
    setInterval(function () {
        fetch('/my-api-endpoint').then(function (res) {
            var data = res.json();
            
            if(!compare(data, cache)){
                cache = data;
                self.postMessage(data)
            }
        })
    
    },1000)

});

pollingWorker.onmessage = function () {
    // render data
}

pollingWorker.postMessage('init');

上面代码中,Worker 每秒钟轮询一次数据,然后跟缓存做比较。如果不一致,就说明服务端有了新的变化,因此就要通知主线程。

实例:Worker 新建 Worker

Worker 线程内部还能再新建 Worker 线程 (目前只有 Firefox 浏览器支持)。下面的例子是将一个计算密集的任务,分配到10个Worker。

主线程代码如下:

var worker = new Worker('worker.js');
worker.onmessage = function (event) {
  document.getElementById('result').textContent = event.data;
};
// worker.js

// settings
var num_workers = 10;
var items_per_worker = 1000000;

// start the workers
var result = 0;
var pending_workers = num_workers;
for (var i = 0; i < num_workers; i += 1) {
  var worker = new Worker('core.js');
  worker.postMessage(i * items_per_worker);
  worker.postMessage((i + 1) * items_per_worker);
  worker.onmessage = storeResult;
}

// handle the results
function storeResult(event) {
  result += event.data;
  pending_workers -= 1;
  if (pending_workers <= 0)
    postMessage(result); // finished!
}

上面代码中,Worker 线程内部新建了10个 Worker 线程,并且依次向这10个 Worker 发送消息,告知了计算的起点和终点。计算任务脚本的代码如下。

// core.js
var start;
onmessage = getStart;
function getStart(event) {
  start = event.data;
  onmessage = getEnd;
}

var end;
function getEnd(event) {
  end = event.data;
  onmessage = null;
  work();
}

function work() {
  var result = 0;
  for (var i = start; i < end; i += 1) {
    // perform some complex calculation here
    result += 1;
  }
  postMessage(result);
  close();
}

相关的API

主线程

浏览器原生提供 Worker() 构造函数,用来供主线程生成 Worker 线程。

var myWorker = new Worker(jsUrl, options);

Worker() 构造函数,可以接受两个参数。第一个参数是脚本的网址(必须要遵守同源政策),该参数是必需的,且只能加载JS脚本,否则会报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。

Worker.onerror:指定 error 事件的监听函数。

Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。

Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。

Worker.postMessage():向 Worker 线程发送消息。

Worker.terminate():立即终止 Worker 线程。

Worker 线程

Web Worker 有自己的全局对象,不是主线程的 window,而是一个专门为 Worker 制定的全局对象。因此定义在 window 上面的对象和方法不是全部都可以使用。

Worker 线程有一些自己的全局属性和方法

self.name: Worker 的名字。该属性只读,由构造函数指定。

self.onmessage:指定message事件的监听函数。

self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。

self.close():关闭 Worker 线程。

self.postMessage():向产生这个 Worker 线程发送消息。

self.importScripts():加载 JS 脚本。

对HTML 语义化标签的理解

HTML5语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如nav表示导航条,类似的还有article、header、footer等等标签。

iframe 是什么? 有什么缺点?

定义:iframe元素会创建包含另一个文档的内联框架。

提示:可以将提示文字放在<iframe></iframe>之间,来提示某些不支持Ifame的浏览器。

缺点:

会阻塞页面的onload事件

搜索引擎无法解读这种页面,不利于SEO(搜索引擎优化排名之类的)

iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

Doctype 作用?严格模式与混杂模式如何区分?有何意义

Doctype 声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严格模式和混杂模式。

严格模式的排版和JS 运作模式是以浏览器支持的最高标准运行。

混杂模式,向后兼容,模拟老式浏览器。防止浏览器无法兼容页面。

即<! DOCTYPE html>会按照 w3c 的标准来渲染页面

Cookie 如何防范 XSS攻击

XSS攻击(跨站脚本攻击)指的是攻击者在返回的HTML中嵌入javascript脚本,为了减轻这些攻击,需要在HTTP头部配上

set-cookie:httponly -- 这个属性可以防止XSS,它会禁止javascript脚本来访问cookie

secure -- 这个属性告诉浏览器仅在请求伪https的时候发送cookie

Cookie和session的区别

前言

Http 是一种无状态的协议,为了分辨链接是谁发起的,就需要我们自己去解决这个问题。不然有些情况下即使是同一个网站我们每打开一个页面也都要登录一下。而Session和Cookie就是为解决这个问题而提出来的两个机制。

应用场景

日常登录一个网站,今天输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是cookie。

session的一个场景是购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息,这里就用到了session。

cookie

Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器,是一种在客户端保持状态的方案。

Cookie的主要内容包括:名字,值,过期时间,路径和域

举个例子:

BIDUPSID: 9D2194F1CB8D1E56272947F6B0E5D47E
PSTM: 1472480791
BAIDUID: 3C64D3C3F1753134D13C33AFD2B38367:FG
ispeed_lsm: 2
MCITY: -131:
pgv_pvi: 3797581824
pgv_si: s9468756992
BDUSS: JhNXVoQmhPYTVENEdIUnQ5S05xcHZMMVY5QzFRNVh5SzZoV0xMVDR6RzV-bEJZSVFBQUFBJCQAAAAAAAAAAAEAAACteXsbYnRfY2hpbGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALlxKVi5cSlYZj
BD_HOME: 1
H_PS_PSSID: 1423_21080_17001_21454_21408_21530_21377_21525_21193_21340
BD_UPN: 123253
sug: 3
sugstore: 0
ORIGIN: 0
bdime: 0

可以看见是key, value的形式,也就是我们说的对应着的名字,值。过期时间是可以设置的,如果不设置,则浏览器关掉就消失了,是存储在内存当中的(Session cookie 或者 transient cookie 不设置时间否则就是按照我们设置的时间来存储在硬盘上的,当过期后自动清除(Persistent cookie 或者 permenent cookie 设置过期时间,比方说我们开机关机关闭再打开浏览器后他都会还存在,前者称之为Session cookie 又叫 transient cookie,后者称之为Persistent cookie 又叫 permenent cookie。路径和域就是对应的域名,a网站的cookie自然不能给b用。

session

session 是存在服务器的一种用来存放用户数据的类Hash Table结构

当浏览器 第一次发送请求时,服务器自动生成了一个HashTable和一个Session ID用来唯一标识这个HashTable,并将其通过响应发送到浏览器。当浏览器第二次发送请求,会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的HashTable。

一般这个值会有一个时间限制,超时后毁掉这个值,默认是20分钟。

Session的实现方式和Cookie有一定关系。试想一下,建立一个连接就生成一个session id,那么打开几个页面就好几个了,这显然不是我们想要的,那么该怎么区分呢?这里就用到了Cookie,我们可以把session id存在Cookie中,然后每次访问的时候将Session id带过去就可以识别了,是不是很方便~

区别

通过上面的简单叙述,很容易看出来最明显的不同是一个在客户端一个在服务端。因为Cookie存在客户端所以用户可以看见,所以也可以编辑伪造,不是十分安全。

Session过多的时候会消耗服务器资源,所以大型网站会有专门的Session服务器,而Cookie存在客户端所以没什么问题。

①存储位置不同

cookie 在客户端浏览器上

session 的数据信息放在服务器上

②存储容量不同

单个cookie保存的数据 <= 4KB, 一个站点最多保存20个Cookie

对于session 来说没有上限,可是对于服务端的性能考虑,session 内不要存放过多的东西,且需要设置session删除机制

③存储方式不同

cookie中只能保管 ASCLL字符串,并且需要通过编码存储为Unicode字符或者二进制数据。

session 中能够存储任何类型的数据,包括 string , interger, list , map 等

④隐私策略不同

cookie 对客户端可见,不安全。

session 存储在服务器上,对客户端是透明,不存在敏感信息泄露。

⑤有效期不同

可以通过设置cookie的属性,使得cookie长期有效

session依赖名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。

⑥服务器压力不同

cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。

session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。

⑦浏览器支持不同

假如客户端浏览器不支持cookie:

cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。

运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。

假如客户端支持cookie:

cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。

session只能在本窗口以及子窗口内有效。

⑧跨域支持上不同

cookie支持跨域名访问。

session不支持跨域名访问。

关于RESTFUL

就是用URL定位资源,用HTTP描述操作

讲讲 viewport 和移动端布局

响应式布局的常用解决方案对比(媒体查询、百分比、rem和vw/vh)

前端开发中,静态网页通常需要适应不同分辨率的设备,常用的自适应解决方案包括媒体查询,百分比,rem和 vw/vh 等。本文从px单位出发,分析了px 在移动端布局中的不足,接着介绍了几种不同的自适应解决方案。

  • px和视口
  • 媒体查询
  • 百分比
  • 自适应场景下的rem解决方案
  • 通过vw/vh来实现自适应

px和视口

在静态网页中,我们经常用像素(px)作为单位,来描述一个元素的宽高以及定位信息。在pc端,通常认为css中,1px所表示的真实长度是固定的。

那么,px真的是一个设备无关,跟长度单位米和分米一样是固定大小的吗?

答案是否定的。下面图1.1 和 图1.2分别表示pc端下和移动端下的显示结果,在网页中我们设置的font-size 统一为 16px

px_text_pc 图1.1 PC端下font-size 为16px 时的显示结果

px_text_mobile图1.2 移动端下font-size为16px 时的显示结果

从上面两幅图的对比可以看出,字体都是16px,显然在pc端中文字正常显示,而在移动端文字很小,几乎看不到,说明在css中1px并不是固定大小,直观从我们发现在移动端1px所表示的长度较小,所以导致文字显示不清楚。

那么css中的1px的真实长度到底由什么决定呢?

为了理清楚这个概念,我们首先介绍像素和视口的概念。

1.像素

像素是网页布局的基础,一个像素表示了计算机屏幕所能显示的最小区域,像素分为两种类型:css像素和物理像素。

我们在js或者css代码中使用的px单位就是指的是css像素,物理像素也称设备像素,只与设备或者说硬件有关,同样尺寸的屏幕,设备的密度越高,物理像素也就越多。下表表示css像素和物理像素的具体区别。

那么css像素与物理像素的转换关系是什么样的呢?

为了明确css像素和物理像素的转换关系,必须先了解视口是什么。

2.视口

广义的视口,是指浏览器显示内容的屏幕区域,狭义的视口包括了布局视口、视觉视口和理想视口。

(1)布局视口(layout viewport)

布局视口定义了pc网页在移动端的默认布局行为,因为通常pc的分辨率较大,布局视口默认为980px。也就是说不设置网页的viewport的情况下,pc端的网页默认会以布局视口为基准,在移动端进行展示。因此我们可以看得出来,默认为布局视口时,根植于pc端的网页在移动端展示很模糊。

(2)视觉视口(visual viewport)

视觉视口表示浏览器内看到的网站的显示区域,用户可以通过缩放来查看网页的显示内容,从而改变视觉视口。视觉视口的定义,就像拿着一个放大镜分别从不同距离观察一个物体,视觉视口仅仅类似于放大镜中显示的内容,因此视觉视口不会影响布局视口的宽度和高度。

(3)理想视口(ideal viewport)

理想视口或者应该全称为“理想的布局视口”,在移动设备中就是指设备的分辨率。换句话说,理想视口或者说分辨率就是给定设备物理像素的情况下,最佳的“布局视口”。

上述视口中,最重要的是明确理想视口的概念,在移动端中,理想视口或者说分辨率跟物理像素之间有什么关系呢?

为了理清分辨率和物理像素之间的联系,我们介绍一个用DRP(Device pixel ratio)设备像素比来表示,则可以写成

1 DPR = 物理像素/分辨率

在不缩放的情况下,一个css像素就对应一个dpr,也就是说,在不缩放

1 CSS像素 = 物理像素/分辨率

此外,在移动端的布局中,我们可以通过viewport元标签来控制布局,比如一般情况下,我们可以通过下述标签使得移动端在理想视口下布局:

<meta id="viewport" name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1; user-scalable=no;">
属性名取值描述
width正整数定义布局视口的宽度,单位为像素
height正整数定义布局视口的高度,单位为像素,很少使用
initial-scale[0,10]初始缩放比例,1表示不缩放
minimum-scale[0,10]最小缩放比例
maximum-scale[0,10]最大缩放比例
user-scalableyes/no是否允许手动缩放页面,默认值为yes

其中我们来看width属性,在移动端布局时,在meta标签中我们会将width设置成为device-width,device-width一般是表示分辨率的宽,通过width=device-width的设置我们就将布局视口设置成了理想的视口。

3.px与自适应

上述我们了解到了当通过viewport元标签,设置布局视口为理想视口时,1个css像素可以表示成:

1 CSS像素 = 物理像素/分辨率

我们知道,在pc端的布局视口通常情况下为980px,移动端以iphone6为例,分辨率为375 * 667,也就是说布局视口在理想的情况下为375px。比如现在我们有一个750px * 1134px的视觉稿,那么在pc端,一个css像素可以如下计算:

PC端: 1 CSS像素 = 物理像素/分辨率 = 750 / 980 =0.76 px

而在iphone6下:

iphone6:1 CSS像素 = 物理像素 /分辨率 = 750 / 375 = 2 px

也就是说在pc端,一个css像素可以用0.76个物理像素来表示,而iphone6中 一个css像素表示了2个物理像素。此外不同的移动设备分辨率不同,也就是1个css像素可以表示的物理像素是不同的,因此如果在css中仅仅通过px作为长度和宽度的单位,造成的结果就是无法通过一套样式,实现各端的自适应。

媒体查询

在前面我们说到,不同端的设备下,在css文件中,1px所表示的物理像素的大小是不同的,因此通过一套样式,是无法实现各端的自适应。由此我们联想:

如果一套样式不行,那么能否给每一种设备各一套不同的像是来实现自适应的效果? yes

使用@media 媒体查询可以针对不同的媒体类型定义不同的样式,特别是响应式页面,可以针对不同屏幕的大小,编写多套样式,从而达到自适应的效果。举例子:

@media screen and (max-width: 960px){
    body{
      background-color:#FF6699
    }
}

@media screen and (max-width: 768px){
    body{
      background-color:#00FF66;
    }
}

@media screen and (max-width: 550px){
    body{
      background-color:#6633FF;
    }
}

@media screen and (max-width: 320px){
    body{
      background-color:#FFFF00;
    }
}

上述的代码通过媒体查询定义了几套样式,通过max-width设置样式生效时的最大分辨率,上述的代码分别对应分辨率在0~320px,320px~550px,550px~768px以及768px~960px的屏幕设置了不同的背景颜色。

通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片。比如给小屏幕手机设置@2x图,为大屏幕手机设置@3x图,通过媒体查询就能很方便的实现。

但是媒体查询的缺点也很明显,如果在浏览器大小改变时,需要改变的样式太多,那么多套样式代码会很繁琐。

百分比

除了用px结合媒体查询实现响应式布局外,我们也可以通过百分比单位“%”来实现响应式的效果。比如当浏览器的宽度或者高度发生变化时,通过百分比单位,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。

为了了解百分比布局,首先要了解的问题是:

css中的子元素中的百分比(%)到底是谁的百分比?

直观的理解,我们可能会认为子元素的百分比完全相对于直接父元素,height 百分比相对于 height,width百分比相对于 width。当然这种理解是正确的,但是根据css的盒式模型,除了height、width属性外,还具有padding、border、margin等等属性。那么这些属性设置成百分比,是根据父元素的哪些属性呢?此外还有border-radius和translate等属性中的百分比,又是相对于什么呢?

1.百分比的具体分析

(1)子元素height和width的百分比

子元素的height或width中使用百分比,是相对于子元素的直接父元素,width 相对于父元素的width,height相对于父元素的height。比如:

<div class="parent">
  <div class="child"></div>
</div>

如果设置:
.father{
width:200px;
height:100px;
}
.child{
width:50%;
height:50%;
}
展示的效果为:
2018-06-22 7 00 29

(2) top和bottom 、left和right

子元素的top和bottom如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度,同样

子元素的left和right如果设置百分比,则相对于直接非static定位(默认定位的)父元素的宽度。

展示的效果为:

2018-06-22 7 42 14

(3)padding

子元素的padding如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。

举例来说:

.parent{
  width:200px;
  height:100px;
  background:green;
}
.child{
  width:0px;
  height:0px;
  background:blue;
  color:white;
  padding-top:50%;
  padding-left:50%;
}

展示的效果为:

2018-06-22 7 55 13

子元素的初始宽高为0,通过padding可以将父元素撑大,上图的蓝色部分是一个正方形,且边长为100px,说明padding不论宽高,如果设置成百分比都相对于父元素的width。

(4)margin

跟padding一样,margin也是如此,子元素的margin如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的width。这里就不具体举例。

5)border-radius

border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度,举例来说:

  <div class="trangle"></div>

设置border-radius为百分比:

.trangle{
  width:100px;
  height:100px;
  border-radius:50%;
  background:blue;
  margin-top:10px;
}

展示效果为:

2018-06-22 8 09 20

除了border-radius外,还有比如translate、background-size等都是相对于自身的,这里就不一一举例。

百分比单位的缺点

从上述对于百分比单位的介绍我们很容易看出如果全部使用百分比单位来实现响应式的布局,有明显的以下两个缺点:

(1)计算困难,如果我们要定义一个元素的宽度和高度,按照设计稿,必须换算成百分比单位。
(2)从小节1可以看出,各个属性中如果使用百分比,相对父元素的属性并不是唯一的。比如width和height相对于父元素的width和height,而margin、padding不管垂直还是水平方向都相对比父元素的宽度、border-radius则是相对于元素自身等等,造成我们使用百分比单位容易使布局问题变得复杂。

自适应场景下的rem解决方案

一个页面html 有个默认的font-size值为16px 即 html { font-size:16px }

此时1rem = 16px, 相当于说 1 rem  html中设置的font-size的值

那么此时会有两种解决方案:

①用媒体@medio 举个例子如下:

@media screen and (min-width:240px) { html, body, button, input, select, textarea { font-size:9px; }}

@media screen and (min-width:320px) { html, body, button, input, select, textarea { font-size:12px; }}// 红米Note2

@media screen and (min-width:360px) { html, body, button, input, select, textarea { font-size:13.5px; }}

@media screen and (min-width:375px) { html, body, button, input, select, textarea { font-size:14.0625px; }} 

②用js设置html的font-size大小

document.documentElement.style.fontSize = document.documentElement.clientWidth /750+ 'px';

缺点有如下:

css样式和js代码有一定的耦合性。且必须将改变font-size的代码放在css样式之前

通过 vw/vh  来实现自适应

什么是vw/vh?

css3中引入了一个新的单位vw/vh,与视图窗口有关,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。各个单位具体的含义如下:

单位含义
vw相对于视窗的宽度,视窗宽度是100vw
vh相对于视窗的高度,视窗高度是100vh
vminvw和vh中的较小值
vmaxvw和vh中的较大值

这里我们发现视窗宽高都是100vw/100vh,那么vw或者vh,下简称vw,很类似百分比单位。vw和%的区别为:

单位含义
%大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
vw/vh相对于视窗的尺寸

从对比中我们可以发现,vw单位与百分比类似,单确有区别,前面我们介绍了百分比单位的换算困难,这里的vw更像"理想的百分比单位"。任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一。

vw单位换算

1px = (1/375)*100 vw

click 在ios上有300ms延迟,原因及如何解决?

(1)粗暴型,禁用缩放

<meta name="viewport" content="widh=device-width,user-scalable=no">

(2)利用FastClick,其原理是:

检测到touchend事件后,立即出发模拟click事件,并且把浏览器300毫秒之后真正出发的时间给阻断掉

addEventListener的参数

addEventListener(event, function, useCapture)

其中,event指定事件名;function指定要事件触发时执行的函数;useCapture指定事件是否在捕获或冒泡阶段执行。

捕获从外层到内层,冒泡从内层到外层

http 状态码说说你知道的

200 ok 请求成功

201 created 已创建并创建了新的资源

202 Accepted 已接受,已经接受请求,但未处理。

204 No Content 无内容,服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档。

301 302 前者资源被永久移动,后者资源临时移动

304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源。

400 Bad Request 客户端请求的语法错误,服务器无法理解

401 unauthorized 请求要求用户的身份认证

403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求

404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可以设置“您所请求的资源无法找”的个性页面。

500 Interal Server Error 服务器内部错误,无法完成请求

501 Not Implemented 服务器不支持请求的功能,无法完成请求。

502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器收到了一个无效的响应。

505 HTTP version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理。

关于304

如果客户端发送了一个带条件的GET,请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。

强缓存、协商缓存什么时候用哪个

因为服务器上的资源不是一直固定不变的,大多数情况下它会更新,这个时候如果我们还访问本地缓存,那么对用户来说,那就相当于资源没有更新,用户看到的还是旧的资源,所以我们希望服务器上的资源更新了浏览器就请求新的资源,没有更新就用本地的缓存,以最大程度的减少因网络请求而产生的资源浪费。

浏览器缓存

浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。根据以上的特点,浏览器缓存有下面的优点:

1.减少冗余的数据传输

2.减少服务器的负担

3.加快客户端加载网页的速度

浏览器缓存是web性能优化的重要方式,那么浏览器缓存的过程究竟是什么样的?

在浏览器第一次发送请求时,本地无缓存,向web服务器发送请求,服务器端响应请求,浏览器端缓存。过程如下:

在第一次请求时,服务器会将页面最后修改时间通过Last-Modified 标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个Etag,并发送给客户端。

当浏览器后续再次进行请求时:

浏览器缓存主要分为强缓存(本地缓存)和协商缓存(弱缓存)。

浏览器在第一次请求发生后,再次发送请求时:

浏览器请求某一资源时,会先获取该资源缓存的header信息,然后根据header 中的Cache-Control 和 Expires 来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的header信息,所以此次请求不会与服务器进行通信。这里判断是否过期,则是强缓存相关。

 如果显示已经过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的header字段信息,比如客户端会通过If-None-Match 头将先前服务器端发送过来的Etag 发送给服务器,服务会对比这个客户端发过来的Etag是否与服务器的相同,若相同,就将If-None-Match 的值设置为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将If-None-Match 设置为true ,返回状态码200,客户端重新解析服务器端返回的数据;客户端还会通过If-Modified-Since 头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端继续使用本地缓存。

强缓存

强缓存是利用Http 头中的Expires 和 Cache-Control 两个字段来控制的,用来表示自愿的缓存时间。强缓存中,普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上Cache-Control:no-cache 和Pragma:no-cache

Expires

Expires 是http1.0 的规范,它的值是一个绝对时间的GMT格式的时间字符串。如果我现在这个网页的Expires 值是 expires:Fri, 14 Apr 2017 10:47:02 GMT 。这个时间代表这个资源的失效时间,主要发送请求时间是在Expires 之前,那么本地缓存始终有效,则在缓存中读取数据。所以这种方式有一个明显的缺点,由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。如果同时出现Cache-Control:max-age 和 Expires,那么max-age 优先级更高。

如我主页的response headers部分如下:

cache-control:max-age=691200
expires:Fri, 14 Apr 2017 10:47:02 GMT

那么表示资源可以被缓存的最长时间为691200秒,会优先考虑max-age

Cache-Control

Cache-Control 是在http 1.1中出现的,主要是利用该字段的max-age 值来进行判断,它是一个相对时间,例如Cache-Control:max-age = 3600 ,代表资源的有效期限是3600秒。cache-control 除了该字段外,还有下面的几个比较常用的设置值:

no-cache :不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。

no-stroe :直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。

public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。

private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

Cache-Control 与 Expires 可以在服务端配置同时启动,同时启用的时候Cache-Control优先级更高。

协商缓存

协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问

普通刷新会启用弱缓存,忽略强缓存。只有在地址栏或收藏夹输入王者、通过链接引用资源等情况下,浏览器才会启用强缓存,这也是为什么有时候我们更新一张图片、一个JS文件、页面内容依然是旧的,但是直接浏览器访问那个图片或文件、看到的内容却是新的。

这个主要涉及到两组header 字段:Etag 和 If-None-Match、Last-Modified 和 If-Modified-Since

复习一下:

Etag 和 If-None-Match

Etag/If-None-Match 返回的是一个校验码。Etag 可以保证每一个资源时唯一的,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否使用缓存。

与Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于Etag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。

Last-Modify / If-Modify-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否使用缓存。

如果在有效期内,则返回304,并且不会返回资源内容,并且不会返回Last-Modify

为什么要有Etag

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;

  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);

  • 某些服务器不能精确的得到文件的最后修改时间。

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

http://caibaojian.com/http-cache-3.html (从缓存策略学习http缓存)

前端优化

降低请求量:合并资源,减少HTTP请求数,minify / gzip压缩,webP,lazyLoad

加快请求速度:预解析DNS,减少域名数,并行加载CDN分发

缓存:HTTP协议缓存请求,离线缓存manifest,离线数据缓存localStorage

渲染:js/css优化,加载顺序,服务端渲染,pipeline

唉,标个颜色后面自习去琢磨下

GET和POST的区别

get参数通过url传递,post放在request body中。

get请求在url中传递的参数是有长度限制的,而post没有。

get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。

get请求只能进行url编码,而post支持多种编码方式

get请求会浏览器主动cache,而post支持多种编码方式。

get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。

GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

GET产生一个TCP数据包;POST产生两个TCP数据包。

HTTP支持的方法

GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT

如何画一个三角形

div {
width:0px;
height:0px;
border-top:10px solid red;
border-right:10px solid transparent;
border-bottom:10px solid transparent;
border-left:10px solid transparent;
}

状态码304 和 200

状态码200:请求已成功,请求所希望的响应头或数据体将随此响应返回。即返回的数据为全量的数据,如果文件不通过GZIP压缩的话,文件是多大,则要有多大传输量。

状态码304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。即客户端和服务器端只需要传输很少的数据量来做文件的校验,如果文件没有修改过,则不需要返回全量的数据。

说一下浏览器缓存

缓存分为两种:强缓存和协商缓存,根据响应的header内容来决定。

强缓存相关字段有expires,cache-control。如果cache-control与expires同时存在的话,cache-control的优先级高于expires。

协商缓存相关字段有Last-Modified/If-Modified-Since,Etag/If-None-Match

HTML5新增的元素

header,footer,nav,aside,section等语义化标签

为input增加了color,emial,data ,range等类型

在存储方面,提供了sessionStorage,localStorage,和离线存储

音频和视频元素audio和vedio,另外还有地理定位,canvas画布,拖放,多线程编程的web worker和websocket协议

在地址栏里输入一个URL,到这个页面呈现出来,中间会发生什么?

输入url 后,首先需要找到这个url域名的服务器ip,为了寻找这个ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存 => 系统缓存 => 路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录,如果没有则查询DNS服务器,得到服务器的ip地址后,浏览器根据这个ip及相应的端口号,构造一个http请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将和这个http请求封装在一个tcp包中,这个tcp包会一次经过传输层,网络层,数据链路层,物理层,达到服务器,服务器解析和这个请求作出相应,返回相应的html给浏览器,因为html是一个属性结构,浏览器根据这个html来构建DOM树,在dom树的构建过程中如果遇到JS脚本和外部JS连接,则会停止构建DOM树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐JS代码应该放在html代码后面,之后根据外部样式,内部样式,内联样式构建一个CSS对象模型树CSSOM树,构建完成后的DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为node节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是页面渲染,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到和谐都会进行并行下载,浏览器对每个域的并行下载数量有一定限制,一般是4-6个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires等首部字段控制。Cache-Control 和 Expires的区别在于 Cache-Control使用相对时间,Expires使用的是基于服务器端的绝对时间,因为存在时间差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验Last-Modified,没有设置ETag则直接验证Last-Modified,再是否返回304。

cookie和session的区别,localstorage和sessionstorage的区别

参考回答:

Cookie和session都可用来存储用户信息,cookie存放于客户端,session存放于服务器端,因为cookie存放于客户端有可能被窃取,所以cookie一般用来存放不敏感的信息,比如用户设置的网站主题,敏感的信息用session存储,比如用户的登陆信息,session可以存放于文件,数据库,内存中都可以,cookie可以服务器端响应的时候设置,也可以客户端通过JS设置cookie会在请求时在http首部发送给客户端,cookie一般在客户端有大小限制,一般为4K,

下面从几个方向区分一下cookie,localstorage,sessionstorage的区别

1、生命周期:

Cookie:可设置失效时间,否则默认为关闭浏览器后失效

Localstorage:除非被手动清除,否则永久保存

Sessionstorage:仅在当前网页会话下有效,关闭页面或浏览器后就会被清除

2、存放数据:

Cookie:4k左右

Localstorage和sessionstorage:可以保存5M的信息

3、http请求:

Cookie:每次都会携带在http头中,如果使用cookie保存过多数据会带来性能问题

其他两个:仅在客户端即浏览器中保存,不参与和服务器的通信

4、易用性:

Cookie:需要程序员自己封装,原生的cookie接口不友好

其他两个:即可采用原生接口,亦可再次封装

5、应用场景:

从安全性来说,因为每次http请求都回携带cookie信息,这样子浪费了带宽,所以cookie应该尽可能的少用,此外cookie还需要指定作用域,不可以跨域调用,限制很多,但是用户识别用户登陆来说,cookie还是比storage好用,其他情况下可以用storage,localstorage可以用来在页面传递参数,sessionstorage可以用来保存一些临时的数据,防止用户刷新页面后丢失了一些参数,

csrf和xss的网络攻击及防范

CSRF:跨站请求伪造,可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶意请求,比如用户登录了一个网站后,立刻在另一个tab 页面访问量攻击者用来制造攻击的网站,这个网站要求访问刚刚登录的网站,并发送了一个恶意请求,这时候CSRF就产生了,比如这个制造攻击的网站使用一张图片,但是这种图片的连接却是可以修改数据库的,这时候攻击者就可以以用户的名义操作这个数据库,防御:使用验证码,检查https头部的refer,使用token

XSS:跨站脚本攻击,是说攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻击,比如获取cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的话不存储在数据库中,往往表现为将攻击代码放在url地址的请求参数中,防御的话为cookie设置httpOnly属性,对用户的输入进行检查,进行特殊字符过滤

怎么看网站的性能如何

检测页面加载的时间,植入脚本或者探针,当用户访问网页时,探针自动采集数据并传回数据库进行分析。

另一个是主动采集性能数据并分析,可以利用第三方的工具,模拟用户发起页面访问请求。

介绍HTTP协议(特征)

HTTP 是一个基于TCP / IP通信协议来传递数据(HTML 文件,图片,查询结果数据等)HTTP属于应用层的面向对象的协议。是一个无状态的协议,且未被加密。

输入URL到页面加载显示完成发生了什么?

DNS解析

TCP连接

发送HTTP请求

服务器处理请求并返回HTTP报文

浏览器解析渲染页面

连接结束

说一下对Cookie和Session的认知,Cookie有哪些限制?

cookie 和 session 都是用来存储数据的。cookie是存储在本地,而session是存储在服务器上的。cookie 不是安全的,别人可以分析在本地上的cookie,伪装假的cookie对服务器进行欺骗。session会在一定的时间内保存在服务器上,但是当访问数量增多时,会占用到服务器的性能。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

描述一下xss和crsf攻击?防御方法?

xss攻击,即跨站脚本攻击,通俗明白讲就是别人将脚本嵌入你的网页中,使得你想访问的网页运行了这段js代码。如果避免跨站攻击的话,我们就得对用户的输入,进行转义。例如<script type='text/javascript'>alert('hello world')</script>。如果直接保存这个字符串的话,然后再输出的话,就会运行JS了。我们需要将这个字符串转义成"&lt;script type='text/javascript'&gt;alert('hello world')&lt;/script&gt;"。

crsf攻击,即跨站请求攻击,就是在别的站点伪造了一个请求,当cookie还没有过期的情况下,攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而进行 crsf 攻击。三种策略可以防御,验证http referer 字段,在请求地址中添加 token 验证,在http 头中自定义属性并验证。

具体有哪些请求头是跟缓存相关的

缓存分为两种:强缓存和协商缓存,根据响应的header内容来决定。

强缓存有expires,Cache-Control。 Cache-Control 优先级高于 expires

协商缓存相关有 Last-Modified / If-Modified-since ,ETag /If-None-Match

cookie有哪些字段可以设置

name字段为一个cookie的名称。

value字段为一个cookie的值。

omain字段为可以访问此cookie的域名。

非顶级域名,如二级域名或者三级域名,设置的cookie的domain只能为顶级域名或者二级域名或者三级域名本身,不能设置其他二级域名的cookie,否则cookie无法生成。

顶级域名只能设置domain为顶级域名,不能设置为二级域名或者三级域名,否则cookie无法生成。

二级域名能读取设置了domain为顶级域名或者自身的cookie,不能读取其他二级域名domain的cookie。所以要想cookie在多个二级域名中共享,需要设置domain为顶级域名,这样就可以在所有二级域名里面或者到这个cookie的值了。
顶级域名只能获取到domain设置为顶级域名的cookie,其他domain设置为二级域名的无法获取。

path字段为可以访问此cookie的页面路径。 比如domain是abc.com,path是/test,那么只有/test路径下的页面可以读取此cookie。

expires/Max-Age 字段为此cookie超时时间。若设置其值为一个时间,那么当到达此时间后,此cookie失效。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。

http字段  cookie的httponly属性。若此属性为true,则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie。

secure 字段 设置是否只能通过https来传递此条cookie

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值