如下總結的跨文檔通訊方法,均是在服務器不參與的狀況下(服務端無需特殊的代碼)實現的html
這裏的通訊,是指頁面A向頁面B傳遞信息node
大體分爲如下三類web
經過客戶端存儲實現通訊數據庫
在頁面跳轉的過程當中攜帶信息跨域
其中第一種方法沒有跨域的限制,且實現的是雙向通訊;第二種方法本質上利用的是同源文檔能夠訪問同一塊數據實現通訊;第三種方法只能實現定向的單次的通訊,且沒有跨域的限制瀏覽器
const http = require('http') const fs = require('fs') http.createServer((req, res) => { fs.readFile(`.${req.url}`, (err, data) => res.end(data)) }).listen(8888)
... <body> index1 <button id='newWindow'>new Window</button> <button id='sendMessage'>Send Message</button> <script> const newWBtn = document.getElementById('newWindow') const sendBtn = document.getElementById('sendMessage') let newWindow = null newWBtn.addEventListener('click', () => { newWindow = window.open(`${document.origin}/index2.html`) }) sendBtn.addEventListener('click', () => { newWindow.postMessage('messageFromIndex1', document.origin) }) window.addEventListener('message', e => console.log(e.data), false) </script> </body> ...
... <body> index2 <script> window.addEventListener('message', receiveMessage, false) function receiveMessage(event){ console.log(event.data) event.source.postMessage('messageFromIndex2', event.origin) } </script> </body> ...
以上代碼實現了經過 index1.html,新建窗口 index2.html安全
index1.html 向 index2.html 發送消息 messageFromIndex1服務器
index2.html 收到來自 index1.html 的消息,並返回消息 meesageFromIndex2cookie
index1.html 和 index2.html 互相傳遞消息的過程並不須要服務端參與post
啓動服務器 node server.js
訪問 http://localhost:8888/index1.html
前後點擊 new Window 和 send Message,能夠看到在 index1.html 和 index2.html 的控制檯中分別出現了 messageFromIndex2 和 messageFromIndex1
經過 postMessage 能夠實現跨域的信息傳遞,所以也要注意傳遞信息的過程當中要檢查信息的安全性
將須要傳遞的信息保存在客戶端中,只有同源的文檔才能訪問,具體的實現方式有
當服務端沒有設置 cookie 爲 HttpOnly 時,能夠在瀏覽器端設置和訪問 cookie,而 cookie 本質上是服務器發送到用戶瀏覽器並保存在瀏覽器上的一塊數據,同源的文檔能夠訪問 cookie
修改 index1.html
... <body> index1 <button id='newWindow'>new Tab</button> <script> const newWBtn = document.getElementById('newWindow') newWBtn.addEventListener('click', () => { document.cookie = 'name=test' window.open(`${document.origin}/index2.html`) }) </script> </body> ...
修改 index2.html
... <body> index2 <script> console.log(document.cookie) </script> </body> ...
能夠看到在 index2.html 的控制檯中打印出了信息 'name=test'
經過 cookie 進行跨文檔通訊,就像同源文檔訪問同一個對象
webStorage 就像一個數據庫,同源的文檔訪問同一個子數據庫
具體操做方法以下
window.localStorage.setItem(key, value)
window.localStorage.getItem(key)
indexedDB 就是一個數據庫
修改 index1.html
... <body> index1 <a href="./index2.html" target="_blank">index2.html</a> <button id='addBtn'>add Data</button> <button id='printBtn'>print Data</button> <script> let request = window.indexedDB.open('mydb', 2) let time = 1 /* 建立objectStore和修改objectStore都只能在db的onupgradeneeded事件中進行 */ request.onupgradeneeded = e => { let db = e.target.result if (!db.objectStoreNames.contains('mystore')) { let objectStore = db.createObjectStore('mystore', { keyPath: 'id' }) objectStore.createIndex('id', 'id', { unique: true }) } } const addBtn = document.getElementById('addBtn') const printBtn = document.getElementById('printBtn') addBtn.addEventListener('click', () => { // 打開數據庫 let request = window.indexedDB.open('mydb', 2) request.onsuccess = e => { // 打開數據庫 得到db let db = e.target.result let transaction = db.transaction(['mystore'], 'readwrite') // 得到 objectStore 至關於數據庫中的表 let objectStore = transaction.objectStore('mystore') // 向表中添加字段 objectStore.put({ id: '100002', name: `time_${time++}`, }) } }) printBtn.addEventListener('click', () => { // 打開數據庫 let request = window.indexedDB.open('mydb', 2) request.onsuccess = e => { // 打開數據庫 得到db let db = e.target.result let transaction = db.transaction(['mystore'], 'readonly') // 得到 objectStore 至關於數據庫中的表 let objectStore = transaction.objectStore('mystore') // 向表中添加字段 objectStore.get('100002').onsuccess = e => console.log(e.target.result) } }) </script> </body> ...
修改 index2.html
... <body> index2 <button id='printBtn'>print Data</button> <script> const printBtn = document.getElementById('printBtn') printBtn.addEventListener('click', () => { // 打開數據庫 let request = window.indexedDB.open('mydb', 2) request.onsuccess = e => { // 打開數據庫 得到db let db = e.target.result let transaction = db.transaction(['mystore'], 'readonly') // 得到 objectStore 至關於數據庫中的表 let objectStore = transaction.objectStore('mystore') // 向表中添加字段 objectStore.get('100002').onsuccess = e => console.log(e.target.result) } }) </script> </body> ...
如此實如今 index1.html 中修改 indexedDB 中存儲的數據時,index2.html 中也能夠訪問到,以此來間接實現通訊
如下這些方法都沒有域的限制,但對跳轉到新頁面的方式有限制
設置 window.name = message
當經過 window.location.href 或 <a href='./index2.html'>index2.html</a>
在當前窗口載入新頁面時,window.name 仍保存着上個頁面所設置的信息
修改 index1.html
... <body> index1 <a href="./index2.html">index2.html</a> <script> window.name = 'messageFromIndex1' </script> </body> ...
修改 index2.html
... <body> index2 <script> console.log(window.name) </script> </body> ...
會在控制檯輸出 messageFromIndex1
修改目標文檔的 url,將想要傳遞的信息保存在 url 的 hash 字段中
設置 window.history.replaceState(window.history,state, document.title, 'message')
從該頁面到新頁面後,經過 document.referrer 就能夠看到來自上個頁面的信息
修改 index1.html
... <body> index1 <a href="./index2.html" target="_blank">index2.html</a> <script> window.history.replaceState(window.history.state, document.title, 'messageFromIndex1') </script> </body> ...
修改 index2.html
... <body> index2 <script> console.log(document.referrer) </script> </body> ...
會在控制檯輸出 http://localhost:8888/messageFromIndex1
這裏利用的是 window.history.replaceState() 修改 url,並不會使頁面從新加載,因此將信息存在 url 中
document.referrer 會保存返回跳轉或打開到當前頁面的那個頁面的 url