日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

前端跨域通信的几种方式

發(fā)布時(shí)間:2023/12/10 HTML 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端跨域通信的几种方式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

前端通信類(lèi)的問(wèn)題,主要包括以下內(nèi)容:

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

同源策略是一個(gè)概念,就一句話。有什么限制,就三句話。能說(shuō)出來(lái)即可。

  • 2、前后端如何通信

如果你不準(zhǔn)備,估計(jì)也就只能說(shuō)出ajax。

  • 3、如何創(chuàng)建Ajax

Ajax在前后端通信中經(jīng)常用到。做業(yè)務(wù)時(shí),可以借助第三方的庫(kù),比如vue框架里的庫(kù)、jQuery也有封裝好的方法。但如果讓你用原生的js去實(shí)現(xiàn),該怎么做?

這就是考察你的動(dòng)手能力,以及框架原理的掌握。如果能寫(xiě)出來(lái),可以體現(xiàn)出你的基本功。

  • 4、跨域通信的幾種方式

這部分非常重要。無(wú)非就是問(wèn)你:什么是跨域、跨域有什么限制、跨域有幾種方式

下面分別講解。

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

同源策略:限制從一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。(來(lái)自MDN官方的解釋)

具體解釋:

(1)源包括三個(gè)部分:協(xié)議、域名、端口(http協(xié)議的默認(rèn)端口是80)。如果有任何一個(gè)部分不同,則源不同,那就是跨域了。

(2)限制:這個(gè)源的文檔沒(méi)有權(quán)利去操作另一個(gè)源的文檔。這個(gè)限制體現(xiàn)在:(要記住)

  • Cookie、LocalStorage和IndexDB無(wú)法獲取。

  • 無(wú)法獲取和操作DOM。

  • 不能發(fā)送Ajax請(qǐng)求。我們要注意,Ajax只適合同源的通信。

前后端如何通信

主要有以下幾種方式:

  • Ajax:不支持跨域。

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

  • CORS:不受同源策略的限制,支持跨域。一種新的通信協(xié)議標(biāo)準(zhǔn)。可以理解成是:同時(shí)支持同源和跨域的Ajax

如何創(chuàng)建Ajax

關(guān)于Ajax請(qǐng)求,可以看本人的基礎(chǔ)文章:Ajax入門(mén)和發(fā)送http請(qǐng)求

在回答 Ajax 的問(wèn)題時(shí),要回答以下幾個(gè)方面:

  • 1、XMLHttpRequest 的工作原理

  • 2、兼容性處理

XMLHttpRequest只有在高級(jí)瀏覽器中才支持。在回答問(wèn)題時(shí),這個(gè)兼容性問(wèn)題不要忽略。

  • 3、事件的出發(fā)條件

  • 4、事件的觸發(fā)順序

XMLHttpRequest有很多觸發(fā)事件,每個(gè)事件是怎么觸發(fā)的。

發(fā)送 Ajax 請(qǐng)求的五個(gè)步驟(XMLHttpRequest的工作原理)

(1)創(chuàng)建XMLHttpRequest 對(duì)象。

(2)使用open方法設(shè)置請(qǐng)求的參數(shù)。open(method, url, 是否異步)。

(3)發(fā)送請(qǐng)求。

(4)注冊(cè)事件。 注冊(cè)onreadystatechange事件,狀態(tài)改變時(shí)就會(huì)調(diào)用。

如果要在數(shù)據(jù)完整請(qǐng)求回來(lái)的時(shí)候才調(diào)用,我們需要手動(dòng)寫(xiě)一些判斷的邏輯。

(5)獲取返回的數(shù)據(jù),更新UI。

發(fā)送 get 請(qǐng)求和 post 請(qǐng)求

get請(qǐng)求舉例:

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title> </head> <body> <h1>Ajax 發(fā)送 get 請(qǐng)求</h1> <input type="button" value="發(fā)送get_ajax請(qǐng)求" id='btnAjax'><script type="text/javascript">// 綁定點(diǎn)擊事件document.querySelector('#btnAjax').onclick = function () {// 發(fā)送ajax 請(qǐng)求 需要 五步// (1)創(chuàng)建異步對(duì)象var ajaxObj = new XMLHttpRequest();// (2)設(shè)置請(qǐng)求的參數(shù)。包括:請(qǐng)求的方法、請(qǐng)求的url。ajaxObj.open('get', '02-ajax.php');// (3)發(fā)送請(qǐng)求ajaxObj.send();//(4)注冊(cè)事件。 onreadystatechange事件,狀態(tài)改變時(shí)就會(huì)調(diào)用。//如果要在數(shù)據(jù)完整請(qǐng)求回來(lái)的時(shí)候才調(diào)用,我們需要手動(dòng)寫(xiě)一些判斷的邏輯。ajaxObj.onreadystatechange = function () {// 為了保證 數(shù)據(jù) 完整返回,我們一般會(huì)判斷 兩個(gè)值if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {// 如果能夠進(jìn)到這個(gè)判斷 說(shuō)明 數(shù)據(jù) 完美的回來(lái)了,并且請(qǐng)求的頁(yè)面是存在的// 5.在注冊(cè)的事件中 獲取 返回的 內(nèi)容 并修改頁(yè)面的顯示console.log('數(shù)據(jù)返回成功');// 數(shù)據(jù)是保存在 異步對(duì)象的 屬性中console.log(ajaxObj.responseText);// 修改頁(yè)面的顯示document.querySelector('h1').innerHTML = ajaxObj.responseText;}}} </script> </body> </html>

post 請(qǐng)求舉例:

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title> </head> <body> <h1>Ajax 發(fā)送 get 請(qǐng)求</h1> <input type="button" value="發(fā)送put_ajax請(qǐng)求" id='btnAjax'> <script type="text/javascript">// 異步對(duì)象var xhr = new XMLHttpRequest();// 設(shè)置屬性xhr.open('post', '02.post.php');// 如果想要使用post提交數(shù)據(jù),必須添加此行xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");// 將數(shù)據(jù)通過(guò)send方法傳遞xhr.send('name=fox&age=18');// 發(fā)送并接受返回值xhr.onreadystatechange = function () {// 這步為判斷服務(wù)器是否正確響應(yīng)if (xhr.readyState == 4 && xhr.status == 200) {alert(xhr.responseText);}}; </script> </body> </html>

onreadystatechange 事件

注冊(cè) onreadystatechange 事件后,每當(dāng) readyState 屬性改變時(shí),就會(huì)調(diào)用 onreadystatechange 函數(shù)。

readyState:(存有 XMLHttpRequest 的狀態(tài)。從 0 到 4 發(fā)生變化)

  • 0: 請(qǐng)求未初始化

  • 1: 服務(wù)器連接已建立

  • 2: 請(qǐng)求已接收

  • 3: 請(qǐng)求處理中

  • 4: 請(qǐng)求已完成,且響應(yīng)已就緒

事件的觸發(fā)條件

事件的觸發(fā)順序

上圖的參考鏈接:

  • 你真的會(huì)使用XMLHttpRequest嗎?

實(shí)際開(kāi)發(fā)中用的 原生Ajax請(qǐng)求

var util = {};//獲取 ajax 請(qǐng)求之后的jsonutil.json = function (options) {var opt = {url: '',type: 'get',data: {},success: function () {},error: function () {},};util.extend(opt, options);if (opt.url) {//IE兼容性處理:瀏覽器特征檢查。檢查該瀏覽器是否存在XMLHttpRequest這個(gè)api,沒(méi)有的話,就用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提交數(shù)據(jù),必須添加此行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); //將字符串轉(zhuǎn)成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

上面這五種方式,在面試時(shí),都要說(shuō)出來(lái)。

1、JSONP

面試會(huì)問(wèn):JSONP的原理是什么?怎么實(shí)現(xiàn)的?

在CORS和postMessage以前,我們一直都是通過(guò)JSONP來(lái)做跨域通信的。

JSONP的原理:通過(guò)<script>標(biāo)簽的異步加載來(lái)實(shí)現(xiàn)的。比如說(shuō),實(shí)際開(kāi)發(fā)中,我們發(fā)現(xiàn),head標(biāo)簽里,可以通過(guò)<script>標(biāo)簽的src,里面放url,加載很多在線的插件。這就是用到了JSONP。

JSONP的實(shí)現(xiàn):

比如說(shuō),客戶端這樣寫(xiě):

<script src="http://www.smyhvae.com/?data=name&callback=myjsonp"></script>

上面的src中,data=name是get請(qǐng)求的參數(shù),myjsonp是和后臺(tái)約定好的函數(shù)名。
服務(wù)器端這樣寫(xiě):

myjsonp({data: {} })

于是,本地要求創(chuàng)建一個(gè)myjsonp 的全局函數(shù),才能將返回的數(shù)據(jù)執(zhí)行出來(lái)。

實(shí)際開(kāi)發(fā)中,前端的JSONP是這樣實(shí)現(xiàn)的:

<script>var util = {};//定義方法:動(dòng)態(tài)創(chuàng)建 script 標(biāo)簽/*** [function 在頁(yè)面中注入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'); //事先約定好的 函數(shù)名window[callbackName] = function () { //根據(jù)回調(diào)名稱(chēng)注冊(cè)一個(gè)全局的函數(shù)if (onsuccess && util.isFunction(onsuccess)) {onsuccess(arguments[0]);}};var script = util.createScript(url + '&callback=' + callbackName, charset); //動(dòng)態(tài)創(chuàng)建一個(gè)script標(biāo)簽script.onload = script.onreadystatechange = function () { //監(jiān)聽(tīng)加載成功的事件,獲取數(shù)據(jù)if (!script.readyState || /loaded|complete/.test(script.readyState)) {script.onload = script.onreadystatechange = null;// 移除該script的 DOM 對(duì)象if (script.parentNode) {script.parentNode.removeChild(script);}// 刪除函數(shù)或變量window[callbackName] = null; //最后不要忘了刪除}};script.onerror = function () {if (onerror && util.isFunction(onerror)) {onerror();}};document.getElementsByTagName('head')[0].appendChild(script); //往html中增加這個(gè)標(biāo)簽,目的是把請(qǐng)求發(fā)送出去};</script>

2、WebSocket

WebSocket的用法如下:

//var ws = new WebSocket('wss://echo.websocket.org'); //創(chuàng)建WebSocket的對(duì)象。參數(shù)可以是 ws 或 wss,后者表示加密。//把請(qǐng)求發(fā)出去ws.onopen = function (evt) {console.log('Connection open ...');ws.send('Hello WebSockets!');};//對(duì)方發(fā)消息過(guò)來(lái)時(shí),我接收ws.onmessage = function (evt) {console.log('Received Message: ', evt.data);ws.close();};//關(guān)閉連接ws.onclose = function (evt) {console.log('Connection closed.');};

Websocket的推薦鏈接:http://www.ruanyifeng.com/blog/2017/05/websocket.html

3、CORS

CORS 可以理解成是既可以同步、也可以異步*的Ajax。

fetch 是一個(gè)比較新的API,用來(lái)實(shí)現(xiàn)CORS通信。用法如下:

// url(必選),options(可選)fetch('/some/url/', {method: 'get',}).then(function (response) { //類(lèi)似于 ES6中的promise}).catch(function (err) {// 出錯(cuò)了,等價(jià)于 then 的第二個(gè)參數(shù),但這樣更好用更直觀});
  • CORS的推薦鏈接:http://www.ruanyifeng.com/blog/2016/04/cors.html

推薦鏈接里有詳細(xì)的配置。

另外,如果面試官問(wèn):“CORS為什么支持跨域的通信?”

答案:跨域時(shí),瀏覽器會(huì)攔截Ajax請(qǐng)求,并在http頭中加Origin。

4、Hash

url的#后面的內(nèi)容就叫Hash。Hash的改變,頁(yè)面不會(huì)刷新。這就是用 Hash 做跨域通信的基本原理。

補(bǔ)充:url的?后面的內(nèi)容叫Search。Search的改變,會(huì)導(dǎo)致頁(yè)面刷新,因此不能做跨域通信。

使用舉例:

場(chǎng)景:我的頁(yè)面 A 通過(guò)iframe或frame嵌入了跨域的頁(yè)面 B。

現(xiàn)在,我這個(gè)A頁(yè)面想給B頁(yè)面發(fā)消息,怎么操作呢?

(1)首先,在我的A頁(yè)面中:

//偽代碼var B = document.getElementsByTagName('iframe');B.src = B.src + '#' + 'jsonString'; //我們可以把JS 對(duì)象,通過(guò) JSON.stringify()方法轉(zhuǎn)成 json字符串,發(fā)給 B

(2)然后,在B頁(yè)面中:

// B中的偽代碼window.onhashchange = function () { //通過(guò)onhashchange方法監(jiān)聽(tīng),url中的 hash 是否發(fā)生變化var data = window.location.hash;};

5、postMessage()方法

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

場(chǎng)景:窗口 A (http:A.com)向跨域的窗口 B (http:B.com)發(fā)送信息。步驟如下。

(1)在A窗口中操作如下:向B窗口發(fā)送數(shù)據(jù):

// 窗口A(http:A.com)向跨域的窗口B(http:B.com)發(fā)送信息Bwindow.postMessage('data', 'http://B.com'); //這里強(qiáng)調(diào)的是B窗口里的window對(duì)象

(2)在B窗口中操作如下:

// 在窗口B中監(jiān)聽(tīng) message 事件Awindow.addEventListener('message', function (event) { //這里強(qiáng)調(diào)的是A窗口里的window對(duì)象console.log(event.origin); //獲取 :url。這里指:http://A.comconsole.log(event.source); //獲取:A window對(duì)象console.log(event.data); //獲取傳過(guò)來(lái)的數(shù)據(jù)}, false);

?

總結(jié)

以上是生活随笔為你收集整理的前端跨域通信的几种方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。