有時候會遇到傻X需求,例如前端單點登陸!遇到需求,就要去想解決辦法,
這裡我會為大家做一個簡單的前端單點登陸的解決方案,
用到的就是postMessage跨域訊息傳輸以及onstorage的監聽。
本文所用的知識點koa架設靜態資源服務、跨域、postMessage的用法、onstorage監聽storage
第一步、架設兩個不同連接埠的服務我們這裡用koa2來搭建兩個服務到不同的端口,來模擬一下真正的工作中需要出現的跨域情況。
很簡單的主要用到koa-static這個中間件
搭建起來也是非常容易的,如果大家想學node相關的知識可以加我微信shouzi_1994 或在博客下面留言你的聯繫方式這裡就不多說廢話了直接上代碼視頻內會有詳細的搭建步驟
// localhost:4000const Koa = require('koa');const path = require('path')const static = require('koa-static')const app = new Koa();//設定靜態資源的路徑const staticPath = './static'app.use(static( path.join( __dirname, staticPath) )) console.log(服務啟動在4000埠)app.listen(4000);// localhost:3000const Koa = require('koa');const path = require('path')const static = require('koa-static' )const app = new Koa();//設定靜態資源的路徑const staticPath = './static'app.use(static( path.join( __dirname, staticPath) ))console.log(服務啟動在4000埠)app.listen(4000);第二步、跨域通訊postMessage
我們先來看看postMessage的API
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他視窗的一個引用,例如iframe的contentWindow屬性、執行window.open傳回的視窗物件、或是命名過或數值索引的window.frames。
message
將要傳送到其他window的資料。它將被結構化克隆演算法序列化。這意味著你可以不受什麼限制的將資料物件安全的傳送給目標視窗而無需自己序列化。 [1]
targetOrigin
透過視窗的origin屬性來指定哪些視窗能接收到訊息事件,其值可以是字串(表示無限制)或是一個URI。在傳送訊息的時候,如果目標視窗的協定、主機位址或連接埠這三者的任一項不符合targetOrigin提供的值,那麼訊息就不會被傳送;只有三者完全匹配,訊息才會被傳送。這個機制用來控制訊息可以傳送到哪些視窗;例如,當用postMessage傳送密碼時,這個參數就顯得尤為重要,必須保證它的值與這條包含密碼的訊息的預期接受者的origin屬性完全一致,來防止密碼被惡意的第三方截獲。如果你明確的知道訊息應該發送到哪個窗口,那麼請始終提供一個有確切值的targetOrigin,而不是。不提供確切的目標將導致資料外洩到任何對資料感興趣的惡意網站。
transfer 可選
是一串和message 同時傳遞的Transferable 物件. 這些物件的所有權將轉移給訊息的接收方,而發送一方將不再保有所有權。
怎麼樣是不是很容易理解,這裡給大家中文化一下。
要傳輸的那個(父)子視窗.postMessage(傳輸的內容, 傳輸到哪個位址, [權限是否轉移(一般不用)]);
提前說一下,要跨域傳輸,必須是父子頁面,也就是說,是透過js Open的頁面,或是ifream嵌套的頁面
好了我們開始來寫程式碼
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>Document</title></head><body> <!-- postMessage和iframe解決普通的跨域問題--> 我是連接埠3000網站的內容<button onclick=send()>發送訊息給兒子</button> <iframe style=display:none src=http://localhost: 4000 frameborder=0></iframe><script> function send() { window.frames[0].postMessage({a:1},http://localhost:4000); // 觸發跨域子頁面的messag事件} window.addEventListener('message', function(event) { console. info('兒子來信了', event); }, false);</script></body></html>
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>Document</title></head><body> <!-- postMessage和iframe解決普通的跨域問題--> 我是連接埠4000網站的內容<button onclick=send()>傳訊息給爸爸</button> <iframe style=display:none src=http://localhost: 4000 frameborder=0></iframe><script> window.addEventListener(message,function(event){ console.log(爸爸來信了:, event) },false) function send() { parent.postMessage({a:1}, 'http://localhost:3000'); // }</script></ body></html>
寫到這裡我們已經實現了父子頁面的跨域通訊,但是這個通訊只發生在一個視窗內啊,並沒有達到我想要的效果,該怎麼辦呢。
監聽數值變化,做出及時反應到這裡大家需要思考,什麼東西是瀏覽器上的所有同網域網站都能看到的呢?
沒錯,storage,我們只需要對這個進行監聽就好了。
這裡我們選擇監聽loacalStorage 現在我們對子頁面做改進
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>Document</title></head><body> <!-- postMessage和iframe解決普通的跨域問題--> 我是連接埠4000網站的內容<button onclick=send()>傳訊息給爸爸</button> <iframe style=display:none src=http://localhost: 4000 frameborder=0></iframe><script> window.addEventListener(message,function(event){ console.log(爸爸來信了:, event) var data = JSON.stringify(event.data) window.localStorage.setItem(data,data) },false) window.onstorage(function(st){ console.log(st .key,st.value) }) function send() { parent.postMessage({a:1}, 'http://localhost:3000'); // }</script></body></html>
看,我們是不是到現在就能夠針對跨域傳輸的內容做出回應了呢?
思考現在我們做到了兩個頁面的跨域通訊,那麼三個到多個的跨域通訊怎麼做呢?其實一個道理啦。現在道理說給你了,寫法自己去體驗一下吧。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。