如下总结的跨文档通讯方法,均是在服务器不参与的状况下(服务端无需特殊的代码)实现的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