基于 postMessage 和 localStorage 的跨域本地存储方案
HTML5 的 postMessage 为解决跨域页面通信提供了一套可控的机制, 而 localStorage 则提供了易用简洁的本地存储方案? 这两者结合起来,能否实现跨域本地存储呢 ?
答案是可以的。假设有 a.com 和 b.com 两个页面。我们想通过 a 页面去修改 b 页面的本地数据。 我们需要做如下步奏:
- 在 a 页面创建一个 iframe ,嵌入 b 页面
- a 页面通过 postMessage 传递指定格式的消息给 b 页面
- b 页面解析 a 页面传递过来的消息内容,调用localStorage API 操作本地数据
- b 页面包装 localStorage 的操作结果,并通过 postMessage 传递给 a 页面
- a 页面解析 b 页面传递回来的消息内容,得到 localStorage 的操作结果
整个过程如下图:
OK,清楚了整个过程,我们就可以封装出相应的组件:CSClient.js 和 csHub.js,来完成这个过程,下面我们来简单实现一下。
先来看CSClient.js,作用于 a 页面,用于创建跨域存储实例,它提供了 get、set、del 这三个方法来操作跨域的数据:
function CSClient(url) {
this.id = this._getId();
this._init(url);
this._origin = this._getOrigin(url);
this._callbacks = {
_get: {},
_set: {},
_del: {}
}
this._bindEvent();
}
CSClient.prototype._getId = function () {
id = 0;
return function () {
return ++id;
}
}();
CSClient.prototype._init = function (url) {
var frame = document.createElement('iframe');
frame.style.display = 'none';
frame.src = url;
document.body.appendChild(frame);
this._hub = frame.contentWindow;
}
CSClient.prototype._getOrigin = function(url) {
var uri, origin;
uri = document.createElement('a');
uri.href = url;
origin = uri.protocol + '//' + uri.host;
return origin;
};
CSClient.prototype._parseMessage = function (method, key, value) {
return JSON.stringify({
method: method,
key