1 Star 2 Fork 0

videring / postmates-js

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

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

PostmatesJS, based on postmate@1.5.2, adds the following:

  • support iframe dom
  • support communicating with at least one iframe
  • support communicating with window.open

PostmatesJS 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

  • Promise-based API for elegant and simple communication.
  • Secure two-way parent <-> children handshake, with message validation.
  • Child expose a retrievable model object that the parent can access.
  • Child emit 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.9kb (minified & gzipped).

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

Installing

PostmatesJS can be installed via NPM.

NPM

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

Glossary

  • Parent: The top level page that will embed an iFrame, creating a Child.
  • Children: The bottom level page loaded within the iFrame or new tab page by window.open.
  • 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

<body>
	<div>Parent Page/div>
	<iframe id='cid1' style="width: 300px; height: 300px;" src="http://localhost:8081/c1.html"></iframe>
	<div id='cid2' style="width: 300px; height: 300px;"></div>
</body>
// Kick off the handshake with the iFrame
PostmatesJS.debug = true;
const open = window.open('http://localhost:8083/c3.html', '_blank')
const handshake = new PostmatesJS([
    {
        container: document.getElementById("cid1"), // first way
        url: "",
        name: "name1"
    }, {
        container: document.getElementById("cid2"), // second way, similar to `postmate`
        url: "http://localhost:8082/c2.html",
        name: "name2"
    }, {
        container: open, // document.getElementById("cid2"), // third way, open a new page with `window.open` 
        url: "http://localhost:8083/c3.html",
        name: "name2"
    }
]);

// When parent <-> child handshake is complete, data may be requested from the child
handshake.then(parentAPIs => {
    parentAPIs.forEach(parentAPI => {
        parentAPI.on('some-event', data => {
            console.log(data)
        }); // Logs "Hello, World!"
        parentAPI.call("demoFunction", {options:"Hello, PostmatesJS!"})
    })
});

localhost:8081/c1.html

PostmatesJS.debug = true
const model = new PostmatesJS.Model({
    demoFunction:(options) =>{
        console.log('child1', options)
    }
 });
model.then(childAPI => {
    childAPI.emit('some-event', 'Hello, World! Child1');
});

localhost:8082/c2.html

PostmatesJS.debug = true
const model = new PostmatesJS.Model({
    //demoFunction:提供给父页面的方法
    //options: 从父页面传入的参数信息
    demoFunction:(options) =>{
        console.log('child2', options)
    }
});
model.then(childAPI => {
    childAPI.emit('some-event', 'Hello, World! Child2');
});

localhost:8083/c3.html

PostmatesJS.debug = true
const model = new PostmatesJS.Model({
    //demoFunction:提供给父页面的方法
    //options: 从父页面传入的参数信息
    demoFunction:(options) =>{
        console.log('child3', options)
    }
});
model.then(childAPI => {
    childAPI.emit('some-event', 'Hello, World! Child3');
});

API

PostmatesJS.debug

// parent.com or child.com
PostmatesJS.debug = true;
new PostmatesJS(options);
Name Type Description Default
debug Boolean Set to true to enable logging of additional information false

PostmatesJS.Promise

// parent.com or child.com
PostmatesJS.Promise = RSVP.Promise;
new PostmatesJS(options);
Name Type Description Default
Promise Object Replace the Promise API that PostmatesJS uses window.Promise

PostmatesJS(options)

// parent.com
new PostmatesJS({
  container: document.body,
  url: 'http://child.com/',
  classListArray: ["myClass"],
  model: { foo: 'bar' }
});

This is written in the parent page. Creates an iFrame at the specified url. Initiates a connection with the child. Returns a Promise that signals when the handshake is complete and communication is ready to begin.

Returns: Promise(child)

Properties

Name Type Description Default
container (optional) DOM Node Element An element to append the iFrame to document.body
url String A URL to load in the iFrame. The origin of this URL will also be used for securing message transport none
classListArray Array An Array to add classes to the iFrame. Useful for styling none
model Object An object literal to represent the default values of the Childs model none

PostmatesJS.Model(model)

// child.com
new PostmatesJS.Model({
  // Serializable values
  foo: "bar",
  // Functions
  height: () => document.height || document.body.offsetHeight,
  // Promises
  data: fetch(new Request('data.json'))
});

This is written in the child page. Calling PostmatesJS.Model initiates a handshake request listener from the Child. Once the handshake is complete, an event listener is bound to receive requests from the Parent. The Child model is extended from the model provided by the Parent.

Returns: Promise(handshakeMeta)

Parameters

Name Type Description Default
model Object An object of gettable properties to expose to the parent. Value types may be anything accepted in postMessage. Promises may also be set as values or returned from functions. {}

child.get(key)

// parent.com
new PostmatesJS({
  container: document.body,
  url: 'http://child.com/'
}).then(child => {
  child.get('something').then(value => console.log(value));
});

Retrieves a value by property name from the Childs model object.

Returns: Promise(value)

Parameters

Name Type Description
key String (required) The string property to lookup in the childs model

child.call(key, data)

// parent.com
new PostmatesJS({
  container: document.body,
  url: 'http://child.com/'
}).then(child => {
  child.call('sayHi', 'Hello, World!');
});

Calls the function sayHi in the Child Model with the parameter Hello, World!

Returns: undefined

Parameters

Name Type Description
key String (required) The string property to lookup in the childs model
data Mixed The optional data to send to the child function

child.destroy()

// parent.com
new PostmatesJS({
  container: document.body,
  url: 'http://child.com/'
}).then(child => child.destroy());

Removes the iFrame element and destroys any message event listeners; if the child is opened with window.open, then Closes the open page.

Returns: undefined


child

new PostmatesJS(options).then(child => {
  child.get('height')
    .then(height => child.frame.style.height = `${height}px`);
});

The iFrame Element that the parent is communicating with

Troubleshooting/FAQ

General

Why use Promises for an evented API?

Promises provide a clear API for fetching data. Using an evented approach often starts backwards. if the parent wants to know the childs height, the child would need to alert the parent, whereas with PostmatesJS, the Parent will request that information from the child in a synchronous-like manner. The child can emit events to the parent as well, for those other use-cases that still need to be handled.

Silent Parent/Child

I've enabled logging but the parent or child is not logging everything.

Postmate.debug needs to be set in both the parent and child for each of them to log their respective information

The child does not respond to communication from the Parent

Make sure that you have initialized PostmatesJS.Model in your child page.

Restrictive Communication

I want to retrieve information from the parent by the child

Postmate (by design) is restrictive in its modes of communication. This enforces a simplistic approach: The parent is responsible for logic contained within the parent, and the child is responsible for logic contained within the child. If you need to retrieve information from parent -> child, consider setting a default model in the parent that the child may extend.

I want to send messages to the child from the parent

This is specifically what the call function is for.

Security

What is the Handshake and why do I need one?

By default, all message events received by any (parent) page can come from any (child) location. This means that the Parent must always enforce security within its message event, ensuring that the child (origin) is who we expect them to be, that the message is a response from an original request, and that our message is valid. The handshake routine solves this by saving the identities of the child and parent and ensuring that no changes are made to either.

How are messages validated?

The origin of the request, the message type, the postMessage mime-type, and in some cases the message response, are all verified against the original data made when the handshake was completed.

License

MIT

Copyright (c) 2016 Dollar Shave Club, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

暂无描述 展开 收起
JavaScript 等 2 种语言
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/videring/postmates-js.git
git@gitee.com:videring/postmates-js.git
videring
postmates-js
postmates-js
master

搜索帮助