Postmate

一个强大、简单、基于 promise 的 postMessage 库。「📭 A powerful, simple, promise-based postMessage library.」

Github stars Tracking Chart

Postmate

一个强大的、简单的、基于 promise 的 postMessage iFrame 通信库。

Postmate 是一个建立在 postMessage 上的基于 promise 的 API。它允许父页面与子 iFrame 跨源对话,而且工作量很小。

你可以直接在 这里 下载编译后的 javascript。

特性

  • 基于 promise 的 API,用于优雅和简单的通信。
  • 安全的双向父 <-> 子握手,并带有消息验证。
  • 子代暴露一个可检索的模型对象,父代可以访问。
  • 子代发出事件,父代可以监听。
  • 父代可以调用子代的函数。
  • 零依赖性。如果需要的话,可以为 Promise API 提供自己的 polyfill 或抽象。
  • 轻量级,大小约为1.6kb(缩小和压缩后)。

注意:虽然底层机制是 window.postMessage(),但只支持 iFrame。

安装

Postmate 可以通过 NPM 安装。

NPM

$ yarn add postmate # Install via Yarn
$ npm i postmate --save # Install via NPM

词汇表

  • Parent:将嵌入 iFrame 的顶层页面,创建一个 Child。
  • Child(子页面):在 iFrame 中加载的底层页面。iFrame 中加载的底层页面。
  • Model(模型):子代向父代公开的对象。
  • Handshake(握手):父框架向子框架标识自己的过程,反之亦然。当握手完成时,两个上下文已经绑定了它们的事件监听器并相互识别。

用法

  1. 父方开始与子方通信。发出握手,子方回应握手回复,完成父方/子方的初始化。两者进行绑定,准备进行安全通信。
  2. Parent 通过属性名从 Child 获取值。子代可以向父代发出消息。Parent 可以调用 Child 模型中的函数。

示例

parent.com

// Kick off the handshake with the iFrame
const handshake = new Postmate({
  container: document.getElementById('some-div'), // Element to inject frame into
  url: 'http://child.com/page.html', // Page to load, must have postmate.js. This will also be the origin used for communication.
  name: 'my-iframe-name', // Set Iframe name attribute. Useful to get `window.name` in the child.
  classListArray: ["myClass"] //Classes to add to the iframe via classList, useful for styling.
});
// When parent <-> child handshake is complete, data may be requested from the child
handshake.then(child => {
  // Fetch the height property in child.html and set it to the iFrames height
  child.get('height')
    .then(height => child.frame.style.height = `${height}px`);
  // Listen to a particular event from the child
  child.on('some-event', data => console.log(data)); // Logs "Hello, World!"
});

child.com/page.html

const handshake = new Postmate.Model({
  // Expose your model to the Parent. Property values may be functions, promises, or regular values
  height: () => document.height || document.body.offsetHeight
});
// When parent <-> child handshake is complete, events may be emitted to the parent
handshake.then(parent => {
  parent.emit('some-event', 'Hello, World!');
});

API

(恕删略。请参见自述文件。)

故障排除/常见问题

一般性问题

Q:为什么要使用 Promises 来做一个事件化的 API?

A:Promises 为获取数据提供了一个清晰的 API。使用事件化的方法往往是倒过来开始的。如果父节点想知道子节点的高度,子节点需要提醒父节点;而对于 Postmate,父节点将以类似于同步的方式向子节点请求该信息。对于那些仍然需要处理的其他用例,子程序也可以向父程序发出事件。

沉默的父/子程序

Q:我已经启用了日志记录功能,但父代或子代并没有记录所有信息。

A:Postmate.debug 需要在父代和子代中设置,以便它们各自记录各自的信息。

Q:子组件不响应来自父组件的通信

A:确保您已经在您的子页面中初始化了 Postmate.Model。

限制性交流

Q:我想通过子代来检索父代的信息。

A:Postmate(在设计上)在沟通模式上是有限制的。这强制了一种简单的方法:父节点负责父节点中包含的逻辑,子节点负责子节点中包含的逻辑。如果您需要从父 -> 子节点检索信息,请考虑在父节点中设置子节点可能扩展的默认模型。

Q:我想从父节点向子节点发送消息。

A:这就是 call 函数的具体作用。

安全性

Q:什么是握手,为什么我需要握手?

A:默认情况下,任何(父)页面收到的所有消息事件都可以来自任何(子)位置。这意味着父页必须始终在其消息事件中强制执行安全,确保子页(原点)是我们期望的人,消息是来自原始请求的响应,并且我们的消息是有效的。握手例程通过保存子代和父代的身份并确保不对其中任何一个进行更改来解决这个问题。

Q:消息是如何验证的?

A:请求的来源、消息类型、postMessage 的 mime 类型,以及某些情况下的消息响应,都会与握手完成时的原始数据进行验证。

许可证

MIT

(The first version translated by vz on 2020.11.21)

Overview

Name With Ownerdollarshaveclub/postmate
Primary LanguageJavaScript
Program languageJavaScript (Language Count: 2)
PlatformWeb browsers
License:MIT License
Release Count30
Last Release Name1.5.2 (Posted on )
First Release Namev0.1.0 (Posted on )
Created At2016-08-01 17:16:06
Pushed At2023-06-02 12:27:05
Last Commit At2020-01-26 08:17:45
Stargazers Count1.8k
Watchers Count47
Fork Count184
Commits Count180
Has Issues Enabled
Issues Count91
Issue Open Count33
Pull Requests Count97
Pull Requests Open Count21
Pull Requests Close Count34
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

A powerful, simple, promise-based postMessage iFrame communication library.

npm
CircleCI
Share

Postmate is a promise-based API built on postMessage. It allows a parent page to speak with a child iFrame across origins with minimal effort.

You can download the compiled javascript directly here


Features

Greenkeeper badge

  • Promise-based API for elegant and simple communication.
  • Secure two-way parent <-> child handshake, with message validation.
  • Child exposes a retrievable model object that the parent can access.
  • Child emits events that the parent can listen to.
  • Parent can call functions within a child
  • Zero dependencies. Provide your own polyfill or abstraction for the Promise API if needed.
  • Lightweight, weighing in at ~ 1.6kb (minified & gzipped).

NOTE: While the underlying mechanism is window.postMessage(), only iFrame is supported.

Installing

Postmate can be installed via NPM.

NPM

$ yarn add postmate # Install via Yarn
$ npm i postmate --save # Install via NPM

Glossary

  • Parent: The top level page that will embed an iFrame, creating a Child.
  • Child: The bottom level page loaded within the iFrame.
  • Model: The object that the Child exposes to the Parent.
  • Handshake: The process by which the parent frame identifies itself to the child, and vice versa. When a handshake is complete, the two contexts have bound their event listeners and identified one another.

Usage

  1. The Parent begins communication with the Child. A handshake is sent, the Child responds with a handshake reply, finishing Parent/Child initialization. The two are bound and ready to communicate securely.

  2. The Parent fetches values from the Child by property name. The Child can emit messages to the parent. The Parent can call functions in the Child Model.


Example

parent.com

// Kick off the handshake with the iFrame
const handshake = new Postmate({
  container: document.getElementById('some-div'), // Element to inject frame into
  url: 'http://child.com/page.html' // Page to load, must have postmate.js. This will also be the origin used for communication.
  classListArray: ["myClass"] //Classes to add to the iframe via classList, useful for styling.
});

// When parent <-> child handshake is complete, data may be requested from the child
handshake.then(child => {

  // Fetch the height property in child.html and set it to the iFrames height
  child.get('height')
    .then(height => child.frame.style.height = `${height}px`);

  // Listen to a particular event from the child
  child.on('some-event', data => console.log(data)); // Logs "Hello, World!"
});

child.com/page.html

const handshake = new Postmate.Model({
  // Expose your model to the Parent. Property values may be functions, promises, or regular values
  height: () => document.height
To the top