- AJAX
- GET和POST请求的区别
- 同源策略、JSONP、跨域方式
- 浏览器架构
- 输入一个Url到加载网页的全过程,发生了什么?
- 浏览器渲染的步骤
- 重绘和回流
- 页面渲染优化
-
什么是AJAX?
AJAX即一种异步请求,可以实现页面局部刷新;
-
AJAX实现的步骤:
-
创建请求对象
-
与服务端创建连接,执行open方法;
-
发送请求,执行send方法;
-
为请求对象绑定onreadystate事件,当readyState为4 且 status为200时处理数据;
-
AJAX封装
- function Ajax(options) {
- var xhr = null;
- var params = formsParams(options.data);
- // 第一步: 创建请求对象
- if(window.XMLHttpRequest) {
- xhr = new XMLHttpRequest();
- } else {
- // 兼容IE6
- xhr = new ActiveXObject("Microsoft.XMLHTTP");
- }
- // 第二步: 连接,执行open和send方法;
- if(options.type == 'GET') {
- xhr.open(options.type, options.url + '?' + params, options.async);
- xhr.send();
- } else if(options.type == 'POST') {
- xhr.open(options.type, options.url, options.async);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- xhr.send(params);
- }
- // 绑定onreadystatechange事件
- xhr.onreadystatechange = function() {
- if(xhr.readyState == 4 && xhr.status == 200) {
- options.success(xhr.responseText);
- }
- }
-
- function formsParams(data) {
- var arr = [];
- for(var i in data) {
- arr.push(i + '=' + data[i]);
- }
- arr.join('&');
- }
- }复制代码
使用方法:
- Ajax({
- type: 'GET',
- url: 'a.php',
- async: true,
- data: {
- name: 'zhangsan',
- age: 10
- },
- success: function(data) {
- console.log(data);
- }
- });复制代码
-
AJAX的优缺点:
优点:
-
实现局部刷新
-
减轻服务器端压力
缺点:
-
破坏浏览器前进和后退机制;
-
一个页面ajax请求过多,会造成页面加载缓慢;
-
数据安全问题不太好,可以采用数据加密的方式;
-
readyState状态码:
0 - open方法还没调用
1 - 已经调用send方法,正在发送请求
2 - send方法已经完成,已经接收到全部相应内容
3- 正在解析相应内容
4 - 相应内容解析完成
-
staus状态码:
200 - 成功
404 - 未找到
5** - 服务器错误
GET和POST请求的区别
GET和POST是HTTP请求的两种方式;
-
区别要点:
get: 缓存/长度受限(2M)/无副作用(不修改资源)/幂等的场景(请求数据与资源无关)
post: 安全/长度无限制/支持更多编码类型(ACII & 二进制)
关于安全方面,其实GET和POST两者都不安全。 虽然POST请求的数据不携带在URL上,但是因为HTTP在网络传输的时候是明文传输的,所以,只要使用抓包工具,能轻而易举的获取数据; 想要安全传输,只有加密,可以前端将传输参数进行加密,也可以才用HTTPS;
-
区别见下图,来源 W3school
同源策略、JSONP、跨域方式
-
含义:
端口号、域名、协议名,三者必须全部相同才符合同源策略,反之即为跨域;
-
JSONP
原理:动态生成script标签,利用script不受跨域的限制,但是缺点是只支持get请求;
封装JSONP方法:
- function jsonp(url, callback, success) {
- var script = document.createElement('script');
- script.src = url;
- script.async = true;
- script.type = 'text/javascript';
- window[callback] = function(data) {
- success && success(data);
- }
-
- document.body.appendChild(script);
- }复制代码
-
跨域的其他方法
-
设置 CORS: Access-Control-Allow-Origin:*
2. postMessage
3. WebSocket
4. iframe
浏览器架构
先解释一个概念: 线程(Thread):线程是进程的一部分,并且执行进程中的一部分程序; 进程 (Process):启动一个程序,就会创建一个进程,操作系统为其分配内存,进程中的所有线程中的所有程序状态都保存到该内存中,关闭程序,进程也会消失,内存会释放;
下面这个图很形象:
不同浏览器中的架构不同:
-
可能是一个有很多线程的进程
-
也可能是有少量线程的多个进程,通过IPC进行通信
Chrome 就是属于多进程之间进行通信,现在是为每个标签创建一个进程,正在尝试为每个站点提供自己的进程;
-
多进程的好处
-
多进程的设计可以使多个标签页面的加载不受其他的影响;
-
安全性和沙盒,每个进程有自己独立的存储空间
-
Chrome浏览器的一些机制
-
由于每个进程都有自己的存储空间,它通常包含公共基础结构的副本(例如V8引擎),这样会消耗很多内存空间;
Chrome浏览器为了节省内存,对进程的数量做了限制,这个因内存和CPU功率而定;
当达到这个限制的时候,浏览器会在同一进程中运行从同一站点打开的多个选项卡;
2. 当Chrome浏览器遇到更强大的硬件时,会将每个服务拆分成不同的进程,从而提供更高的稳定性;但是如果资源有限的设备上,会将服务整合到一个进程中,从而节省内存。Android上已经实现了服务的整合;
-
浏览器的组成
-
用户界面(User Interface)
-
浏览器引擎(browser engine)
-
渲染引擎(rendering engine)
-
网络(Networking)
-
用户界面后段(UI Backend)
-
JavaScript解析器(JavaScript Interpreter)
-
数据存储(Data persistence)
下图形象的展示了浏览器的组成:
输入一个Url到加载网页的全过程,发生了什么?
-
域名解析:浏览器将URL解析出相对应的服务器的IP地址(现在本地浏览器的DNS缓存中查找,没有的话,再向浏览器默认的DNS服务器发送查询请求,同时缓存),并从url中解析出端口号
-
浏览器与目标服务器建立一条TCP连接(三次握手);
-
浏览器向服务器发送一条HTTP请求报文
-
服务器返回给浏览器一条HTTP响应报文
-
关闭连接,解析文档
-
浏览器进行渲染
-
如果文档中资源加载就再次建立连接,直至资源全部加载完毕
浏览器渲染的步骤
-
HTML解析出DOM Tree
-
CSS解析出Style Rules
-
两者关联生成Render Tree
-
Layout(布局)根据Render Tree 计算每个节点的信息
-
Painting 根据计算好的信息进行渲染整个页面
浏览器解析文档的过程中, 如果遇到script标签,会立即解析脚本,停止解析文档(因为JS可能会改变DOM和CSS,如果继续解析会造成浪费)。 如果是外部script, 会等待脚本下载完成之后在继续解析文档。现在script标签增加了defer和async属性,脚本解析会将脚本中改变DOM和css的地方解析出来,追加到DOM Tree 和 Style Rules上
重绘和回流
回流(reflow):当页面发生重新布局的过程。元素的几何尺寸发生变化时,需要重新计算节点信息,也就是执行了渲染步骤的第4步;
重绘(repaint):屏幕的一部分需要重新绘制,比如css背影色变化,颜色变化等。
回流比重绘成本高的多得多;
举例说明
- $('body').css('color', 'red'); // repaint
- $('body').css('margin', '2px'); // reflow, repaint
-
- var bstyle = document.body.style; // cache
-
- bstyle.padding = "20px"; // reflow, repaint
- bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint
-
- bstyle.color = "blue"; // repaint
- bstyle.backgroundColor = "#fad"; // repaint
-
- bstyle.fontSize = "2em"; // reflow, repaint
-
- // new DOM element - reflow, repaint
- document.body.appendChild(document.createTextNode('dude!'));复制代码
但是浏览器不会像上边那样,每改一次样式都会重新reflow和repaint一次。一般来说,浏览器会把这样的操作积攒一波,然后reflow一次。
页面渲染优化
基于对渲染过程的了解,推荐一下优化:
-
HTML文档结构层次尽量少,最好不深于6层
-
脚本尽量放后边,避免组织页面加载
-
少量首屏样式可以放在便签内
-
样式结构层次尽量简单
-
脚本减少DOM操作,减少回流,尽量缓存访问DOM的样式信息
-
尽量减少JS修改样式,可以通过修改class名的方式解决
-
减少DOM查找,缓存DOM查找结果
-
动画在屏幕外或页面滚动时,尽量停止