实现原理:
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 的操作结果
下面简单的实现一下:
在A页面:
1 /* 2 API: 3 csclient.get("http://b.test.com","name",callback); 4 csclient.set("http://b.test.com","name","chenjian",callback); 5 csclient.del("http://b.test.com","name",callback); 6 */ 7 var csclient = (function () { 8 var _get = function (url,key,fn) { 9 var value = { 10 _key :key, 11 _method : "get" 12 }; 13 getIframeWindow(url).postMessage(value,url); 14 //给window对象绑定message事件处理 15 addEvent(handMessage) 16 } 17 18 var _set = function (url,key,value,fn) { 19 var _value = { 20 _key : key, 21 _vaule :value, 22 _method : "set" 23 }; 24 getIframeWindow(url).postMessage(_vaule,url); 25 //给window对象绑定message事件处理 26 addEvent(handMessage) 27 } 28 29 var _del = function () function (url,key,fn) { 30 var value = { 31 _key :key, 32 _method : "del" 33 }; 34 getIframeWindow(url).postMessage(_vaule,url); 35 //给window对象绑定message事件处理 36 addEvent(handMessage) 37 } 38 39 function getIframeWindow (url) { 40 var _iframe = document.createElement("iframe"); 41 _iframe.src = url; 42 _iframe.style.display = "none"; 43 window.body.appendChild(_iframe); 44 var iframeWindow = _iframe.contentWindow; 45 return iframeWindow; 46 } 47 function addEvent(func) { 48 if (window.addEventListener) { 49 window.addEventListener("message", func, false); 50 }else{ 51 window.attachEvent("onmessage", func); 52 } 53 } 54 function handMessage (event) { 55 var event = event || window.event; 56 //验证是否来自预期内的域,如果不是不做处理,这样也是为了安全方面考虑 57 if(event.origin === url){ 58 //处理传过来的数据; 59 fn(event.data); 60 } 61 } 62 return { 63 get : _get, 64 set : _set, 65 del : _del 66 } 67 })();
在B页面:
1 /* 2 API: 3 cshub.init("http://a.test.com"); 4 */ 5 var cshub = (function () { 6 var _cshub = function (url) { 7 addEvent(handMessage); 8 function handMessage(event) { 9 var event = event || window.event; 10 //验证是否来自预期内的域,如果不是不做处理,这样也是为了安全方面考虑 11 if(event.origin === url){ 12 if(event.data._method=="get") { 13 getFn(event.data._method) 14 }else if (event.data._method=="set") { 15 setFn(event.data._method) 16 }else { 17 delFn(event.data._method) 18 } 19 } 20 } 21 function addEvent(func) { 22 if (window.addEventListener) { 23 window.addEventListener("message", func, false); 24 }else{ 25 window.attachEvent("onmessage", func); 26 } 27 } 28 29 function getFn (data) { 30 window.parent.postMessage(window.localStorage["data._key"],url); 31 } 32 33 function setFn (data) { 34 window.localStorage["data._key"] = data._value; 35 window.parent.postMessage("设置成功"); 36 } 37 38 function delFn (data) { 39 window.localStorage.removeItem("data._key"); 40 window.parent.postMessage("删除成功"); 41 } 42 } 43 return { 44 init : _cshub 45 }; 46 })();
上面的代码徒手写的没做测试,如果有误还望指出。谢谢