window.postMessage 解决 Vue 和 原生 html 混合开发的问题
由于历史项目的问题,原生采用的是 jquery,我们无法显著和快速的针对某个模块进行开发。当然,Vue 的话可以快速的帮我们解决这个问题
常见的解决方案有几种
- 1、iframe 嵌入
- 2、单页面使用 Vue Spa
new Vue()绑定 ID - 3、通过服务端渲染,ajax 获取 纯 Html 进行 dom 操作嵌入到 body 中
我们在现有的项目改造中,通过 第 2 种方案,将 登录页面 进行改造过,适用于固定且稳定迭代次数少的页面,并且与企业页面耦合程度较轻适合使用
第 3 种方案的话,适用于纯 列表或 非动态脚本控制的页面,例如文章列表,评论列表等,豆瓣的部分列表采用的则是此方案
当然,以上 3 中方案都不适用于 需要 Seo 进行优化的页面
这里我们要解决的场景为 一个完成任务的页面,该任何模块与其他页面 基本上 0 耦合,也只收集页面数据。其中的 iframe 只用于 写数据,客户端用于读数据。并不会和服务数据有过多交集。
且 iframe 端,需要在多处进行使用
window.postMessage
window.postMessage() 方法可以安全地实现跨源通信。意思则为:在两端,客户端 和 嵌入 iframe 端可以进行相互通信
首先,我们在这里定义一套描述
引入 iframe 端 叫: 客户端
被引入 iframe 端 叫: 被引端
按照常见的机制,我们针对 iframe 进行操纵时,我们可以直接通过 dom 阶段进行控制
<body>
<div class="container">
<iframe src="http://192.168.50.9:5500/iframe.html" frameborder="0"></iframe>
</div>
</body>
<script>
var iframe = document.querySelector('iframe');
iframe.document.body.style.backgroundColor = 'red';
....
但是,安全机制层面来讲,官方描述为
对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数 Document.domain 设置为相同的值) 时,这两个脚本才能相互通信。
但是这里的话,我们可以 window.postMessage 来规避此问题
这里列出几个核心方法
-
发送数据
<iframe src="http://192.168.50.9:5500/iframe.html" frameborder="0"></iframe> <script> document.querySelector('iframe').iframe.postMessage("我的消息", "*") </script> -
接受数据
<script> window.addEventListener("message", (event) => { console.log(event) }, false); </script> -
安全限制
postMessage(message, origin)
<script>
document.querySelector('iframe').iframe.postMessage("我的消息", "https://developer.mozilla.org")
</script>
当 origin 设置 * 后,是允许任何人进行处理的,不会有跨域等相关问题。
查看 demo 演示
surest-sky.github.io/iframe/clie…