文章目录
- Iframe内嵌相互传递
- BroadcastChannel同标签页数据传递
- localStorage中间人传递
- 未完待续...
Iframe内嵌相互传递
使用window.postMessage()
的这个html5特性去跨域传递数据,不受跨域限制。
父层:
sendMes(){ // 向iframe发送
let iframdom = this.$refs.iframdom // 拿到iframe的dom
let _window = iframdom.contentWindow // 拿到iframe的window对象
let _document = iframdom.contentDocument // 拿到iframe的document对象
_window.postMessage({type: 'sendMes', text: '内容'}, '*')
// 注意点:1 第一个参数传内容用对象装,因为webpack会默认主动触发一次,
// 即使sendMes没执行,这样被第一次触发的时候我们能通过对象的内容去区分。
// 2 第二个参数写传入的地址是什么,如果不限制地址写*即可
}
window.addEventListener("message", (e) => { // 接收子层
// e.data及postMessage的第一个参数,e.origin及postMessage的第二个参数
})
子层:
window.addEventListener("message", (e) => { // 接收父层
// e.data及postMessage的第一个参数,e.origin及postMessage的第二个参数
})
sendOut(){ // 向父层发送
window.top.postMessage({type: 'sendMes', text: '内容'}, '*')
}
个人对这个api的看法:
- 能够支持跨域,这样不同项目的网站都能相互通信了。
- 当传输的内容多了,整个工程到处都是postMessage,到处监听,会非常的混乱(建议监听统一放到类似App.vue的组文件中)。
- 父层与子层需要定好规则,例如你的项目是子层,就要去问负责开发父层网站的开发人员,怎么按照他们的规范去传递数据和获取回数据
这里推荐篇基础使用文章:【记录postMessage的详细使用】
再推荐篇补充的:【终于搞懂了 Iframe (跨窗口通信)】
BroadcastChannel同标签页数据传递
这个api适合同一个浏览器中,访问多个标签页,标签页之间的通信:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<button id="btn">点击</button>
<script>javascript">
let btnDom = btn
const channel = new BroadcastChannel('card')
btnDom.onclick = function () {
channel.postMessage({
a: 1
})
}
channel.onmessage = (e) => {
console.log('监听到信息', e.data);
}
</script>
</body>
</html>
当a标签页点击了按钮,b标签页就能够接收到数据。兼容性也很好。
当然在框架中使用有些注意事项:
用添加监听器的方式去监听channel的信息传递,这样好销毁内存
javascript">channel.addEventListener('message', handler)
channel.removeEventListener('message', handler) // 销毁
还有一个要注意的,如果postMessage时传入的是框架里的响应式变量是会报错的,传入的时候用…处理下。
综上,最好单独写个js文件去调用BroadcastChannel:
javascript">const channel = new BroadcastChannel('demo')
export function sendMsg(type, content) {
channel.postMessage({
type,
content,
})
}
export function listenMsg(callback) {
const handler = (e) => {
callback && callback(e.data)
}
channel.addEventListener('message', handler)
return ()=>{
channel.removeEventListener('message', handler) // 让组件在使用的时候能够得到销毁函数,在生命周期钩子中销毁
}
}
localStorage中间人传递
localStorage是可以跨页签的,只要是同域的都共用一个localStorage缓存,利用这个特性可以:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<button id="setData">存储</button>
<button id="getData">获取</button>
<script>javascript">
let setDataDom = setData
let getDataDom = getData
setDataDom.onclick = function () {
localStorage.setItem('a', 1)
}
getDataDom.onclick = function () {
console.log(localStorage.getItem('a'));
}
</script>
</body>
</html>
iframe嵌套相同域名的页面应该也是可以正常使用的,不过
- 多占用localStorage资源
- 无法做到主动接收
这里提个醒sessionStorage每个页签都是独立的