本文是学习慕课网上课程前端跳槽面试必备技巧的学习笔记,便于之后复习。本文参照前端跨域通信的几种方式
- 什么是同源策略及限制
- 前后端如何通信
- 如何创建Ajax
- 跨域通信的几种方式
1.同源策略及限制
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。主要是用于隔离潜在恶意文件的关键的安全机制。
源包含:协议、域名、端口(默认80)。三个中任何一个不一样,就是源不一样,就是跨域。
限制:不是一个源的文档不能操作另一个源的文档。
主要限制在以下方面:1)Cookie、localStorage和IndexDB无法获取;2)无法获取另一个源的DOM;3)AJAX请求不能发送
2.前后端如何通信
Ajax是一种同源通信的方式
Websocket不受同源策略的限制
CORS支持跨域通信和同源通信
3.如何创建Ajax
-
1、XMLHttpRequest 的工作原理
-
2、兼容性处理 // XHR只有在高级浏览器中才支持。在回答问题时,这个兼容性问题不要忽略。
-
3、事件的出发条件
-
4、事件的触发顺序
Ajax是什么?
Ajax 是一种异步请求数据的一种技术,能够刷新局部网页数据而不是重新加载整个网页,对于改善用户的体验和程序的性能很有帮助。
发送 Ajax 请求的五个步骤(XMLHttpRequest的工作原理)
①创建XHR(XMLHttpRequest)对象,XHR对象用来和服务器交换数据。
var xhttp;
if (window.XMLHttpRequest) {
//现代主流浏览器
xhttp = new XMLHttpRequest();
} else {
// 针对浏览器,比如IE5或IE6
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
②使用XHR对象的open()创建请求和send()方法发送资源请求给服务器。
xmlhttp.open(method,url,async) method包括get 和post,url主要是文件或资源的路径,async参数为true(代表异步)或者false(代表同步)
如:
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
③使用XHR对象的responseText或responseXML属性获得服务器的响应。
④onreadychange捕获请求的状态码。当发送请求到服务器,我们想要服务器响应执行一些功能就需要使用onreadystatechange函数,每次XHR对象的readyState发生改变都会触发onreadystatechange函数。onreadystatechange属性存储一个当readyState发生改变时自动被调用的函数。
readyState属性,XHR对象的状态,改变从0到4,0代表请求未被初始化,1代表服务器连接成功,2请求被服务器接收,3处理请求,4请求完成并且响应准备。
⑤判断状态吗是否成功,调用ajax的responseText属性返回数据,更新UI。
<body>
<h1>Ajax 发送 get 请求</h1>
<input type="button" value="发送get_ajax请求" id='btnAjax'>
<script type="text/javascript">
// 绑定点击事件
document.querySelector('#btnAjax').onclick = function () {
// 发送ajax 请求 需要 五步
// (1)创建异步对象
var ajaxObj = new XMLHttpRequest();
// (2)设置请求的参数。包括:请求的方法、请求的url。
ajaxObj.open('get', 'ajax_info.txt');
// (3)发送请求
ajaxObj.send();
//(4)注册事件。 onreadystatechange事件,状态改变时就会调用。
//如果要在数据完整请求回来的时候才调用,我们需要手动写一些判断的逻辑。
ajaxObj.onreadystatechange = function () {
// 为了保证 数据 完整返回,我们一般会判断 两个值
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
// 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
// 5.在注册的事件中 获取 返回的 内容 并修改页面的显示
console.log('数据返回成功');
// 数据是保存在 异步对象的 属性中
console.log(ajaxObj.responseText);
// 修改页面的显示
document.querySelector('h1').innerHTML = ajaxObj.responseText;
}
}
}
</script>
</body>
使用jQuery来实现Ajax请求和处理
参数说明:
cache: true缓存页面 false不缓存页面(默认: true,dataType为script和jsonp时默认为false)
type: GET /POST 请求方式 ("POST" 或 "GET"), 默认为 "GET"。
注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。
async: true/false 默认为true异步请求
false同步请求 注意,同步请求会将锁住浏览器,用户其它操作必须等待请求完成才可以执行。
data:发送到服务器的数据。将自动转换为请求字符串格式
dataType: json/jsonp预期服务器返回的数据类型 "json":返回 JSON 数据;"jsonp" JSONP 格式。
success:( data, textStatus, jqXHR) 请求成功后的回调函数
var getData = function () {
$.ajax({
url: "/Home/PostAlbum",
type: "POST",
dataType: "json",
data: { AlbumName: "shanghai", Entered: "5/9/2013" },
success: function (data) {
},
error: function () {
}
});
}
4.跨域通信的几种方式? (重要)
JSONP、Hash、postMessage、WebSocket、CORS
(1).JSONP
原理:利用<script>标签的异步加载实现
ajax请求受同源策略影响,不允许进行跨域请求, <script>标签的src属性并不被同源策略所约束,所以可以跨域的js脚本并执行。利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
JSONP的实现:
客户端:
<script src="http://www.abc.com/?data=name&callback=myjsonp"></script>
上面的src中,data=name
是get请求的参数,myjsonp
是和后台约定好的函数名。
服务器端:
myjsonp({
data: {}
})
本地要求创建一个myjsonp 的全局函数,才能将返回的数据执行出来。
实际开发中,前端的JSONP是这样实现的:
<script>
var util = {};
//定义方法:动态创建 script 标签
/**
* [function 在页面中注入js脚本]
* @param {[type]} url [description]
* @param {[type]} charset [description]
* @return {[type]} [description]
*/
util.createScript = function (url, charset) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
charset && script.setAttribute('charset', charset);
script.setAttribute('src', url);
script.async = true;
return script;
};
/**
* [function 处理jsonp]
* @param {[type]} url [description]
* @param {[type]} onsucess [description]
* @param {[type]} onerror [description]
* @param {[type]} charset [description]
* @return {[type]} [description]
*/
util.jsonp = function (url, onsuccess, onerror, charset) {
var callbackName = util.getName('tt_player'); //事先约定好的 函数名
window[callbackName] = function () { //根据回调名称注册一个全局的函数
if (onsuccess && util.isFunction(onsuccess)) {
onsuccess(arguments[0]);
}
};
var script = util.createScript(url + '&callback=' + callbackName, charset); //动态创建一个script标签
script.onload = script.onreadystatechange = function () { //监听加载成功的事件,获取数据
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = script.onreadystatechange = null;
// 移除该script的 DOM 对象
if (script.parentNode) {
script.parentNode.removeChild(script);
}
// 删除函数或变量
window[callbackName] = null; //最后不要忘了删除
}
};
script.onerror = function () {
if (onerror && util.isFunction(onerror)) {
onerror();
}
};
document.getElementsByTagName('head')[0].appendChild(script); //往html中增加这个标签,目的是把请求发送出去
};
</script>
jquery使用jsonp
var getData = function () {
$.ajax({
type : "get",
async: false,
url : "http://www.practice-zhao.com/student.php?id=1",
dataType: "jsonp",
jsonp:"callback", //请求php的参数名
jsonpCallback: "jsonhandle",//成功时的回调函数。jsonhandle是另一个域的函数名
success : function(data) {
alert("age:" + data.age + "name:" + data.name);
}
});
}
(2).WebSocket
WebSocket的用法如下:
var ws = new WebSocket('wss://echo.websocket.org'); //创建WebSocket的对象。参数可以是 ws 或 wss,后者表示加密。
//把请求发出去
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
//对方发消息过来时,我接收
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
//关闭连接
ws.onclose = function (evt) {
console.log('Connection closed.');
};
Websocket的推荐参考链接:http://www.ruanyifeng.com/blog/2017/05/websocket.html
(3).CORS
CORS 可以理解成是既可以同步、也可以异步*的Ajax。
fetch 是一个比较新的API,用来实现CORS通信。用法如下:
// url(必选),options(可选)
fetch('/some/url/', {
method: 'get',
}).then(function (response) { //类似于 ES6中的promise
}).catch(function (err) {
// 出错了,等价于 then 的第二个参数,但这样更好用更直观
});
- CORS的推荐参考链接:http://www.ruanyifeng.com/blog/2016/04/cors.html
另外,如果面试官问:“CORS为什么支持跨域的通信?”
答案:跨域时,浏览器会拦截Ajax请求,并在http头中加Origin。
(4).Hash
url的#
后面的内容就叫Hash。Hash的改变,页面不会刷新。这就是用 Hash 做跨域通信的基本原理。
补充:url的?
后面的内容叫Search。Search的改变,会导致页面刷新,因此不能做跨域通信。
使用举例:
场景:我的页面 A 通过iframe或frame嵌入了跨域的页面 B。
现在,我这个A页面想给B页面发消息,怎么操作呢?
(1)首先,在我的A页面中:
//伪代码
var B = document.getElementsByTagName('iframe');
//我们可以把JS 对象,通过 JSON.stringify()方法转成 json字符串,发给 B
B.src = B.src + '#' + 'jsonString';
(2)然后,在B页面中:
// B中的伪代码
window.onhashchange = function () { //通过onhashchange方法监听,url中的 hash 是否发生变化
var data = window.location.hash;
};
(5)postMessage()方法
H5中新增的postMessage()方法,可以用来做跨域通信。
场景:窗口 A (http:A.com
)向跨域的窗口 B (http:B.com
)发送信息。步骤如下。
1.在A窗口中操作如下:向B窗口发送数据:
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Bwindow.postMessage('data', 'http://B.com'); //这里强调的是B窗口里的window对象
2.在B窗口中操作如下:
// 在窗口B中监听 message 事件
Awindow.addEventListener('message', function (event) { //这里强调的是A窗口里的window对象
console.log(event.origin); //获取 :url。这里指:http://A.com
console.log(event.source); //获取:A window对象
console.log(event.data); //获取传过来的数据
}, false);