正文
一、了解Postmate
一个强大的、简单的、基于 promise 的 postMessage iFrame 通信库。 Postmate 是一个建立在 postMessage 上的基于 promise 的 API。它允许父页面与子 iFrame 跨源对话,而且工作量很小。
简单理解:就是支持iframe之间的通信,
举个例子:一个页面使用iframe引入了另一个页面,两个页面要相互传值,就可以用到Postmate
AB是两个独立的页面,要在A中引入B就要使用iframe,而他们之间的通信就可以使用Postmate
现在应该清楚Postmate的具体作用了吧
二、Postmate的特性
- 基于 promise 的 API,用于优雅和简单的通信。
- 安全的双向父 <-> 子握手,并带有消息验证。
- 子代暴露一个可检索的模型对象,父代可以访问。
- 子代发出事件,父代可以监听。
- 父代可以调用子代的函数。
- 零依赖性。如果需要的话,可以为 Promise API 提供自己的 polyfill 或抽象。
- 轻量级,大小约为1.6kb(缩小和压缩后)。
三、安装
//yarn
$ yarn add postmate # Install via Yarn
//npm
$ npm i postmate --save # Install via NPM
四、用法
这里使用一个简单的例子让初学者轻松上手使用
4.1 结构搭建
首先先创建两个文件夹,一个父页面(parent)一个子页面(child)
为什么要两个文件夹呢? 因为这是两个不同页面,也不一定在本地,两个是单独的模块。本地测试所以建在同一个文件夹下。
先看一下页面结构
先创建src来存放页面资源,一个html和一个js
然后使用命令npm init -yes初始化项目
然后使用命令npm install --save-dev webpack安装webpack (请先跳转下面webpack)
4.2 初始化页面
parent:使用parent标记父页面,并在下方使用iframe嵌入子页面
<style>
.content {
width: 200px;
height: 100px;
text-align: center;
font-size: 28px;
font-weight: 700;
background-color: pink;
color: #fff;
}
</style>
<body>
<div class="content">
parent
</div>
<div>
<iframe src="./child.html" frameborder="0" id="iframe-container"></iframe>
</div>
</body>
<script src="./parent.js"></script>
child:
<style>
.content {
width: 200px;
height: 100px;
text-align: center;
font-size: 28px;
font-weight: 700;
background-color: skyblue;
color: #fff;
}
</style>
<body>
<div class="content">
child
</div>
</body>
<script src="./child.js"></script>
嵌入之后的效果是这样的:
4.3 如何传值
当页面复杂之后就需要相互传值,但该如何传值呢,继续看
在一开始就已经安装了Postmate,所以在父页面和子页面都需要引入这个插件
4.3.1 子传父
parent:先看代码,下面解析
import PostMate from "Postmate";
const handshake = new PostMate({
container: document.getElementById('iframe-container'),
url: './child.html',
name: 'my-iframe-name',
classListArray: ["myClass"]
});
handshake.then(child => {
child.on('someEvent', (data) => {
console.log('someEvent', data);
});
});
- 首先先引入Postmate插件
- 创建Postmate实例
-
- 参数
- container:获取iframe的dom元素,-- 这里是用id获取
- url:子页面的路径 -- 这里是绝对路径
- ... -- 后面暂时不重要
- 使用.then的方式与子页面建立联系
- child.on是监听事件 当子页面发布这个事件的时候就会触发回调函数,不清楚的可以去看看发布订阅模式
child:先看代码,下面解析
import PostMate from "Postmate";
const handshake = new PostMate.Model({
height: () => document.height || document.body.offsetHeight
});
handshake.then(parent => {
parent.emit('someEvent', '这是子页面!!')
});
- 同上先引入
- 创建子页面实例 -- 先这么理解
- 然后与父页面建立联系,
- 建立完联系发布一个事件
parent.emit('someEvent', '这是子页面!!') - someEvent是事件名,这边发布这个事件名,在父页面就会触发相应事件名的回调
- 后面的是传过去的数据
这就实现了子页面传数据到父页面
4.3.2 父传子
parent:
handshake.then(child => {
child.on('someEvent', (data) => {
console.log('someEvent', data);
const iframe = document.querySelector('#iframe-container')
iframe.contentWindow.postMessage({
text: '收到!这里是父页面over~'
}, '*');
});
});
当你收到子页面发布的信息后就会调用这个方法,那我们就返回一个信息回去,
先获取iframe的dom元素,然后就使用iframe.contentWindow.postMessage的方式把数据传回去
child:
window.addEventListener('message', function(e) {
console.log(e);
console.log(e.data);
console.log(e.data.text);
})
子页面就监听message事件就可以获取父页面传回来的数据啦
当子页面发布(emit)这个事件的时候把
someEvent 这是子页面!!发送给父页面,父页面收到之后并传回一个数据给子页面下面
讲到这里Postmate的最基础的使用就已经讲完了,还有更加进阶的使用,还是要根据具体的项目来改变逻辑,但是方法就是这么简单,可以参考文档Postmate文档
ps:
总结
这里需要讲一下为什么要使用到webpack,如果你有在跟着写的话应该已经发现问题了,一定会报错,为什么呢? 因为原生js使用import导入就使用了esmodule的方式,所以会出现问题,这里最合理的方式就是将js打包后引入,就可以完美解决这个问题。
webpack
如果不会使用webpack打包的同学,可以参考文档webpack文档,我也写了一篇webpack的基础使用也可以看看