前言

前端通信类的问题,主要包括以下内容:

  • 1、什么是同源策略及限制

同源策略是一个概念,就一句话。有什么限制,就三句话。能说出来即可。

  • 2、前后端如何通信

如果你不准备,估计也就只能说出ajax。

  • 3、如何创建Ajax

Ajax在前后端通信中经常用到。做业务时,可以借助第三方的库,比如vue框架里的库、jQuery也有封装好的方法。但如果让你用原生的js去实现,该怎么做?

这就是考察你的动手能力,以及框架原理的掌握。如果能写出来,可以体现出你的基本功。

  • 4、跨域通信的几种方式

这部分非常重要。无非就是问你:什么是跨域、跨域有什么限制、跨域有几种方式

下面分别讲解。

同源策略的概念和具体限制

同源策略:限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。(来自MDN官方的解释)

具体解释:

(1)包括三个部分:协议、域名、端口(http协议的默认端口是80)。如果有任何一个部分不同,则不同,那就是跨域了。

(2)限制:这个源的文档没有权利去操作另一个源的文档。这个限制体现在:(要记住)

  • Cookie、LocalStorage和IndexDB无法获取。

  • 无法获取和操作DOM。

  • 不能发送Ajax请求。我们要注意,Ajax只适合同源的通信。

前后端如何通信

主要有以下几种方式:

  • Ajax:不支持跨域。

  • WebSocket:不受同源策略的限制,支持跨域。

  • CORS:不受同源策略的限制,支持跨域。一种新的通信协议标准。可以理解成是:同时支持同源和跨域的Ajax

如何创建Ajax

关于Ajax请求,可以看本人的基础文章:Ajax入门和发送http请求

在回答 Ajax 的问题时,要回答以下几个方面:

  • 1、XMLHttpRequest 的工作原理

  • 2、兼容性处理

XMLHttpRequest只有在高级浏览器中才支持。在回答问题时,这个兼容性问题不要忽略。

  • 3、事件的出发条件

  • 4、事件的触发顺序

XMLHttpRequest有很多触发事件,每个事件是怎么触发的。

发送 Ajax 请求的五个步骤(XMLHttpRequest的工作原理)

(1)创建XMLHttpRequest 对象。

(2)使用open方法设置请求的参数。open(method, url, 是否异步)。

(3)发送请求。

(4)注册事件。 注册onreadystatechange事件,状态改变时就会调用。

如果要在数据完整请求回来的时候才调用,我们需要手动写一些判断的逻辑。

(5)获取返回的数据,更新UI。

发送 get 请求和 post 请求

get请求举例:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<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', '02-ajax.php');// (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>
</html>

post 请求举例:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body>
<h1>Ajax 发送 get 请求</h1>
<input type="button" value="发送put_ajax请求" id='btnAjax'>
<script type="text/javascript">// 异步对象var xhr = new XMLHttpRequest();// 设置属性xhr.open('post', '02.post.php');// 如果想要使用post提交数据,必须添加此行xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");// 将数据通过send方法传递xhr.send('name=fox&age=18');// 发送并接受返回值xhr.onreadystatechange = function () {// 这步为判断服务器是否正确响应if (xhr.readyState == 4 && xhr.status == 200) {alert(xhr.responseText);}};
</script>
</body>
</html>

onreadystatechange 事件

注册 onreadystatechange 事件后,每当 readyState 属性改变时,就会调用 onreadystatechange 函数。

readyState:(存有 XMLHttpRequest 的状态。从 0 到 4 发生变化)

  • 0: 请求未初始化

  • 1: 服务器连接已建立

  • 2: 请求已接收

  • 3: 请求处理中

  • 4: 请求已完成,且响应已就绪

事件的触发条件

事件的触发顺序

上图的参考链接:

  • 你真的会使用XMLHttpRequest吗?

实际开发中用的 原生Ajax请求

var util = {};//获取 ajax 请求之后的jsonutil.json = function (options) {var opt = {url: '',type: 'get',data: {},success: function () {},error: function () {},};util.extend(opt, options);if (opt.url) {//IE兼容性处理:浏览器特征检查。检查该浏览器是否存在XMLHttpRequest这个api,没有的话,就用IE的apivar xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');var data = opt.data,url = opt.url,type = opt.type.toUpperCase();dataArr = [];}for (var key in data) {dataArr.push(key + '=' + data[key]);}if (type === 'GET') {url = url + '?' + dataArr.join('&');xhr.open(type, url.replace(/\?$/g, ''), true);xhr.send();}if (type === 'POST') {xhr.open(type, url, true);// 如果想要使用post提交数据,必须添加此行xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");xhr.send(dataArr.join('&'));}xhr.onload = function () {if (xhr.status === 200 || xhr.status === 304) { //304表示:用缓存即可。206表示获取媒体资源的前面一部分var res;if (opt.success && opt.success instanceof Function) {res = xhr.responseText;if (typeof res === 'string') {res = JSON.parse(res);  //将字符串转成jsonopt.success.call(xhr, res);}}} else {if (opt.error && opt.error instanceof Function) {opt.error.call(xhr, res);}}};}

Ajax 的推荐链接:https://segmentfault.com/a/1190000006669043

跨域通信的几种方式

方式如下:

  • 1、JSONP

  • 2、WebSocket

  • 3、CORS

  • 4、Hash

  • 5、postMessage

上面这五种方式,在面试时,都要说出来。

1、JSONP

面试会问:JSONP的原理是什么?怎么实现的?

在CORS和postMessage以前,我们一直都是通过JSONP来做跨域通信的。

JSONP的原理:通过<script>标签的异步加载来实现的。比如说,实际开发中,我们发现,head标签里,可以通过<script>标签的src,里面放url,加载很多在线的插件。这就是用到了JSONP。

JSONP的实现:

比如说,客户端这样写:

<script src="http://www.smyhvae.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>

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');B.src = B.src + '#' + 'jsonString';  //我们可以把JS 对象,通过 JSON.stringify()方法转成 json字符串,发给 B

(2)然后,在B页面中:

 // B中的伪代码window.onhashchange = function () {  //通过onhashchange方法监听,url中的 hash 是否发生变化var data = window.location.hash;};

5、postMessage()方法

H5中新增的postMessage()方法,可以用来做跨域通信。既然是H5中新增的,那就一定要提到。

场景:窗口 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.comconsole.log(event.source);  //获取:A window对象console.log(event.data);    //获取传过来的数据}, false);

前端跨域通信的几种方式相关推荐

  1. 前端跨域请求get_解决前端跨域请求的几种方式

    利用 JSONP 实现跨域调用 说道跨域调用,可能大家首先想到的或者听说过的就是 JSONP 了. 1.1 什么是JSONP JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问 ...

  2. window.postMessage - 前端跨域通信

    window.postMessage - 前端跨域通信 window.postMessage() 语法 The dispatched event 安全问题 示例 注意 HTMLIFrameElemen ...

  3. AJAX异步请求解决跨域问题的三种方式

    一 什么是跨域 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说We ...

  4. 前端跨域问题的几种解决方案

    前端跨域问题的几种解决方案 参考文章: (1)前端跨域问题的几种解决方案 (2)https://www.cnblogs.com/xinxingyu/p/6075881.html 备忘一下.

  5. web服务器与网页表单通信,前端与后端通信的几种方式

    只有知道了历史,才能更好的把握现在和未来. 在项目中,通常前端开发主要完成两件事情,一是界面搭建,一是数据交互. 下面是我总结前端与后端交互的几种方式,本文只作简单介绍,不做深入了解. 一.AJAX ...

  6. 跨域资源共享的10种方式(转)

    同源策略 在客户端编程语言中,如JavaScript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同源策略规定跨域之间的脚本是隔离的,一个域的脚本 ...

  7. 跨域资源共享的10种方式

    同源策略 在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同源策略规定跨域之间的脚本是隔离的,一个域的脚本 ...

  8. jquery读取json文件跨域_跨域方法的若干种方式

    一.跨域的解释 那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制, a.com 域名下的js无法操作 b.com 或是 c.a.com 域名下的对象.当协议.子域名.主域名.端口号 ...

  9. 实现cookie跨域共享的两种方式

    目录 跨域概念 为何限制跨域? 如何安全跨域?(如何实现跨域主要参考这里) 如何实现cookie跨域共享? cookie的概念 cookie的特性 跨多域共享cookie( a.com和b.com共享 ...

最新文章

  1. 缓存雪崩,缓存穿透,缓存预热,缓存热备都是什么鬼?
  2. Nitrozme Animation Studio Packages Mac(AE插件拓展包)
  3. Linux运行8086代码,* linux下编译,链接,运行,汇编程序
  4. 负离子程序员的一组未来手绘,酷毙了
  5. contenteditable
  6. ubuntu 安装ssh 服务
  7. 无法理解高等数学怎么办?
  8. 从「广义斯托克斯公式」结合「外微分公式」导出「牛顿-莱布尼茨公式」、「格林公式」、「高斯公式」、「斯托克斯公式」
  9. 如何用手机压缩JPG格式图片?一步轻松搞定
  10. 混凝土墙开洞_请教各位大神,混凝土墙体开洞通常有几种方法
  11. 解决Unknown column XXX in ‘field list‘问题
  12. シェリーヌ / 老师
  13. 什么是“天道左旋、地道右旋”?
  14. 计算机网络实验之验证性实验
  15. 2021 buaa 计组上机P3和P4 单周期CPU 3道课上考试题
  16. <Operating System Concepts> 第九版 第一章习题答案(原创)
  17. 算法笔记(1)-常用推荐算法总结
  18. 吐血整理!14个编写Spring MVC控制器的实用小技巧
  19. 字典大全(修改,添加,删除)所有遍历
  20. C++通过ODBC方式连接数据库SQLServer及增删查改操作【图书借阅系统为例】

热门文章

  1. 动画理解Dijkstra算法过程
  2. python有大括号吗_只有我一个人觉得Python取消了大括号而显得结构更加混乱了吗?...
  3. asp向不同的用户发送信息_【asp.net core 系列】 1 带你了解一下asp.net core
  4. java 堆内存分析_JVM内存堆布局图解分析
  5. 用python绘制图形_python绘制图形
  6. 怎么把字符串变成数组_字符串哈希:从零开始的十分钟包会教程
  7. python类有什么用_python 定制类 有什么用
  8. python流行趋势_Python流行度再创新高,学Python就从风变编程开始
  9. Sublime优美设置(待续)
  10. iOS手势操作简介(三)