一:Iframe父页面与子页面之间的调用javascript
专业词语解释以下:php
Iframe:iframe元素是文档中的文档。css
window对象: 浏览器会在其打开一个HTML文档时建立一个对应的window对象。可是,若是一个文档定义了一个或者多个框架html
(即:包含一个或者多个frame或者iframe标签),浏览器就会为原始文档建立一个window对象,再为每一个iframe建立额外的window对象,这些额外的window对象是原始窗口的子窗口。前端
contentWindow: 是指指定的iframe或者iframe所在的window对象。html5
1. 父页面与子页面之间的调用。java
如今咱们能够慢慢作demo来分别讲解下,假若有iframe父页面为 iframe1.html, 父页面上有2个子页面 分别为iframe2.html 和 iframe3.html。jquery
父页面iframe1.html代码以下:web
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="jquery1.7.js"></script> </head> <body> <iframe src="http://localhost/iframe/iframe3.html" id = "iframe3"></iframe> <iframe src="http://localhost/iframe/iframe2.html" id = "iframe2"></iframe> <div class="iframe1">父页面</div> <script> function test2() { console.log(1); } </script> </body> </html>
子页面iframe2.html代码以下:ajax
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="jquery1.7.js"></script> </head> <body> <div id="test">aaa</div> <div class="iframe2">子页面</div> <script> function b() { console.log("我是子页面"); } function iframe3Page() { console.log("iframe3页面调用iframe2页面"); } </script> </body> </html>
1. 子页面iframe2.html调用父页面 iframe1.html的元素以下代码:
console.log($('.iframe1',parent.document));
2. 子页面iframe2.html调用父页面iframe1.html的函数以下代码:
parent.test2();
注意:父页面iframe1.html页面 中test2方法不能放在$(function(){}), 放在里面就调用不到。
3. 子页面iframe2.html调用自身的iframe(假如父页面有不少iframe,获取自身iframe不经过id或者name属性).
1.首先咱们能够在父页面上写一个函数 用来获取页面全部的iframe,以后进行遍历,进行判断当前的window对象是否相同。以下代码:
function getFrame(f){ var frames = document.getElementsByTagName("iframe"); for(i=0;i<frames.length;i++){ if(frames[i].contentWindow == f){ return(frames[i]) } } }
2. 在子页面iframe2.html中以下调用父页面的方法 getFrame.
/* 获取自身的iframe */ var aa = parent.getFrame(this); console.log(aa); $(aa).attr("flag",true);
给iframe2设置属性 flag: true, 以下截图:
4. 父页面iframe1.html调用子页面 iframe2.html的元素及函数.
以下调用有误的:
console.log(document.getElementById("iframe2").contentWindow.b());
由于iframe2.html 有可能未加载完成,因此要等iframe2加载完成后再进行调用,
因此咱们须要 iframe2.onload = function(){}; 这样再进行调用。为了兼容IE,咱们能够以下封装一个方法:
function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } // 调用方式以下: // 父页面调用子页面iframe2的方法 var iframe2 = document.getElementById("iframe2"); iframeIsLoad(iframe2,function(){ iframe2.contentWindow.b(); // 打印出 我是子页面 // 父页面获取子页面iframe2的元素 var iframeDom = $(".iframe2",iframe2.contentWindow.document); console.log(iframeDom); });
二:理解JSONP跨域技术的基本原理
Javascript是一种在web开发中常用的前端动态脚本技术,在javascript中,有一个很重要的安全限制,被称为"same-Origin-Policy"同源策略,这一策略对于javascript代码可以访问的页面内容做了很重要的限制,即javascript只能访问与包含它的文档在同协议,同域名,同端口的脚本进行交互;
JSONP的基本原理是:利用在页面中建立<script>节点的方法向不一样域提交http请求的方法称为JSONP。
JSONP的具体实现方法以下:
首先咱们为了演示跨域,咱们在host文件夹下绑定以下2个域名以下:
127.0.0.1 abc.example1.com
127.0.0.1 def.example2.com
其中在abc.example1.com域名下有一个a.html页面;访问页面路径以下:
http://abc.example1.com/iframe/a.html
1. 咱们在域名下abc.example1.com下的a.html页面引入一个域名为def.example2.com下的a.js文件;以下:
<script type="text/javascript" src="http://def.example2.com/iframe/a.js"></script>
而后在a.js代码变为以下:
function jsonp(){
alert(1)
}
jsonp();
最后咱们在域名下abc.example1.com下的a.html页面运行下能够看到弹出对话框 "1";咱们能够看到引入不一样域名下的js文件也能跨域执行;
2. 若是我在域名为def.example2.com下的a.js文件可否调用a.html的方法名呢?咱们继续来演示这个demo;咱们在abc.example1.com下的a.html引入文件以下:
<script>
function jsonp(){
alert(1)
}
</script>
<script type="text/javascript" src="http://def.example2.com/iframe/a.js"></script>
其中域名为def.example2.com下的a.js内容为:jsonp(); 咱们继续来运行下页面,能够看到,仍是能够弹出对话框 1;
3. 若是我在外面的调用方法可否传递一个参数呢?咱们继续和第二点同样,只是方法里面多了一个参数传进去便可:以下代码:
def.example2.com下的a.js内容为:jsonp("我是来测试的");abc.example1.com下的a.html文件内容为:
<script>
function jsonp(html){
alert(html)
}
</script>
<script type="text/javascript" src="http://def.example2.com/iframe/a.js"></script>
咱们运行下页面a.html,也能够看到弹出了对话框 "我是来测试的"文案;因此,咱们就能够经过这种方法来给页面中传入外站的数据;能够实现JSONP的跨域数据;
理解JSONP执行过程以下:
首先在客户端注册一个callback(好比jsonpcallback),而后把callback名字(好比叫jsonp123456)传给服务器端,服务器端获得callback名字后,须要用jsonp123456(),把将要输出的json内容包括起来,此时,服务器生成的json数据才能被客户端正确接收;而后以javascript语法的方式,生成一个function,function的名字就是传递回来的参数jsonp123456.而后就能够在客户端直接运行调用jsonp123456这个函数了;
演示代码以下:
在域名下abc.example1.com下的a.html页面代码以下:
动态建立script标签,给script动态设置src值为域名def.example2.com,这样就实如今不一样的域名下了;
以下代码:
<script> function jsonp123456(data){ alert(data.name); // tugenhua alert(data.age); // 28 alert(data.single); // yes } var eleScript= document.createElement("script"); eleScript.type = "text/javascript"; eleScript.src = "http://def.example2.com/iframe/a.js?jsonpcallback=jsonp123456"; document.getElementsByTagName("HEAD")[0].appendChild(eleScript); </script> //在def.example2.com域名下的a.js代码以下: jsonp123456({"name":'tugenhua','age':'28','single':'yes'});
分析: 在a.html下给服务器端发送请求,而且给服务器端传递参数 jsonpcallback=jsonp123456;服务器端拿到jsonpcallback这个参数后;须要用jsonp123456(),把将要输出的json内容包括起来,此时,服务器生成的json数据才能被客户端正确接收;而后以javascript语法的方式,生成一个function,function的名字就是传递回来的参数jsonp123456.而后就能够在客户端直接运行调用jsonp123456这个函数了;
如上演示的代码; 以后分别弹出data.name;data.age;及data.single;
JSONP的优势:
它不像XMLHttpRequest对象实现ajax请求受到同源策略的限制,它在全部的浏览器都支持,
好比古老的IE6也支持,而且在请求完成后能够经过callback的方式传回结果;
JSONP的缺点:
1. 只支持get请求,不支持post请求,它只支持http跨域的请求状况,
不能解决不一样域的两个页面之间如何进行javascript调用的问题;
2. 因为它是get请求,传递的参数都拼在url后面,所以数据安全性不高;
三:iframe之间通讯问题
1. iframe通讯 分为:同域通讯 和 跨域通讯。所谓同域通讯是指 http://localhost/demo/iframe/iframeA.html 下的a.html页面嵌套 iframe 好比: <iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA">的B.html页面,这两个页面数据进行通讯,好比我想在父页面A.html 调用子页面当中的函数 咱们很容易想到或者google下 ;document.getElementById('iframeA').contentWindow.b(); 这种方法,其中b 是子页面B.html中的一个函数。可是这样调用下有个问题我纠结了好久,就是既然在火狐下报这样的错误, 以下图所示:
b不是个函数 可是我在子页面明明定义了这么一个函数,那么为何会报这样的错误呢?通过仔细分析及google,发现有这么一个问题须要理解,当iframe没有加载完成后 我就去执行这个js会报这样的错误,因此就试着在火狐下 用iframe.onload 这个函数 进行测试,果真没有报错,是正确的 因此就肯定是这个问题。因此就想写个兼容IE和火狐 google写个函数 来肯定iframe已经加载完成!,其实给个回调函数来调用咱们上面的方法。
综合上面的思路 A.html 就能够写个这样的代码:
<iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA"></iframe> <div id="topName">topNddddddddddddddddame</div> <script> function A(){ alert("A"); } var iframe = document.getElementById('iframeA'); iframeIsLoad(iframe,function(){ var obj = document.getElementById('iframeA').contentWindow; obj.b(); }); function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } </script> B.html 代码以下: var b = function(){ alert("B"); };
2.子页面调用父页面的函数很简单,只要这样搞下就ok了,window.parent.A();
3. 子页面取父页面元素的值: window.parent.document.getElementById("topName").innerHTML等方法。
二: iframe跨域通讯。
iframe跨域访问通常分为2种状况,第一种是同主域,不一样子域的跨域。 第二种是:不一样主域跨域。
1、 是同主域下面,不一样子域之间的跨域;能够经过document.domain 来设置相同的主域来解决。
假如如今我有个域 abc.example.com 下有个页面叫abc.html, 页面上嵌套了一个iframe 以下:
<iframe src="http://def.example.com/demo/def.html" id="iframe2" style="display:none;"></iframe>,
我想在abc域下的页面abc.html 访问 def域下的def.html 咱们都知道因为安全性 游览器的同源策略的限制,js不能操做页面不一样域下 不一样协议下 不一样端口的页面,因此就要解决跨域访问了,假如父页面abc.html 页面有个js函数:
function test(){console.log(1);};
我想在子页面调用这个函数 仍是按照上面的同域方式调用 parent.test();这样,经过在火狐下看 已经跨域了 解决的办法是 在各个js函数顶部 加一句 document.domain = 'example.com',就能够解决了。
abc.html代码以下:
<iframe src="http://def.example.com/demo/def.html" id="iframe2" style="display:none;"></iframe> // 跨域 子页调用父页的 函数 (假设是下面test函数) document.domain = 'example.com'; function test(){console.log(1);};
def.html代码以下:
/* * 子页调用父页的方法 */ document.domain = 'example.com'; //window.top.test(); window.parent.test();
仍是这两个页面 我想父页调用子页 以下方法:
a.html代码以下:
/* * 跨域 父页想调用子页的的函数 */ document.domain = 'example.com'; var iframe = document.getElementById('iframe2'); iframeIsLoad(iframe,function(){ var obj = iframe.contentWindow; obj.child(); }); function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } }
假如如今def.html页面有个child函数 代码以下:
document.domain = 'example.com'; function child(){console.log('我是子页');}
就能够跨域调用了 无论是子页面调用父页面 仍是父页面调用子页面。一切ok!
三:是不一样主域跨域;
虽然google有几种方法关于不一样主域上的跨域问题 有经过location.hash方法或者window.name方法或者html5及flash等等,
可是我以为下面iframe这种方法值得学习下,以下图所示:
域a.com的页面request.html(即http://a.com/demo/ajax/ajaxproxy/request.html)里面嵌套了一个iframe指向域b.com
(http://b.com/demo/ajax/ajaxproxy/response.html)的response.html,而response.html里又嵌套了域a.com的proxy.html。
思路:要实现a.com域下的request.html页面请求域b.com下的process.php,能够将请求参数经过url传给response.html,由response.html向process.php发起真正的ajax请求(response.html与process.php都属于域b.com),而后将返回的结果经过url传给proxy.html,最后因为proxy.html和request.html是在同个域下,因此能够在proxy.html利用window.top 将结果返回在request.html完成真正的跨域。
ok, 先看看页面结构
a.com域下有:
request.html
proxy.html
b.com域下有:
response.html
Process.php
先来看看request.html页面以下:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> </head> <body> <p id="result">这里将会填上响应的结果</p> <a id="sendBtn" href="javascript:void(0)">点击,发送跨域请求</a> <iframe id="serverIf" style="display:none"></iframe> <script> document.getElementById('sendBtn').onclick = function() { var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html', fn = 'GetPerson', //这是定义在response.html的方法 reqdata = '{"id" : 24}', //这是请求的参数 callback = "CallBack"; //这是请求全过程完成后执行的回调函数,执行最后的动做 CrossRequest(url, fn, reqdata, callback); //发送请求 } function CrossRequest(url,fn,reqdata,callback) { var server = document.getElementById('serverIf'); server.src = url + '?fn=' +encodeURIComponent(fn) + "&data=" +encodeURIComponent(reqdata) + "&callback="+encodeURIComponent(callback); } //回调函数 function CallBack(data) { var str = "My name is " + data.name + ". I am a " + data.sex + ". I am " + data.age + " years old."; document.getElementById("result").innerHTML = str; } </script> </body> </html>
这个页面其实就是要告诉response.html:我要让你执行你定义好的方法GetPerson,而且要用我给你的参数'{"id" : 24}'。
response.html纯粹是负责将CallBack这个方法名传递给下一位仁兄proxy.html,而proxy.html拿到了CallBack这个方法名就能够执行了,
由于proxy.html和request.html是同域的。
response.html代码以下:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> </head> <body> <iframe id="proxy"></iframe> <script> // 通用方法 ajax请求 function _request (reqdata,url,callback) { var xmlhttp; if(window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function(){ if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { var data = xmlhttp.responseText; callback(data); } } xmlhttp.open('POST',url); xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8"); xmlhttp.send(reqdata); } // 通用方法 获取url参数 function _getQuery(key) { var query = location.href.split('?')[1], value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]); return value; } //向process.php发送ajax请求 function GetPerson(reqdata,callback) { var url = 'http://b.com/demo/ajax/ajaxproxy/process.php'; var fn = function(data) { var proxy = document.getElementById('proxy'); proxy.src = "http://a.com/demo/ajax/ajaxproxy/Proxy.html?data=" + encodeURIComponent(data) + "&callback=" + encodeURIComponent(callback); }; _request(reqdata, url, fn); } (function(){ var fn = _getQuery('fn'), reqdata = _getQuery("data"), callback = _getQuery("callback"); eval(fn + "('" + reqdata +"', '" + callback + "')"); })(); </script> </body> </html>
这里其实就是接收来自request.html的请求获得请求参数和方法后向服务器process.php发出真正的ajax请求,而后将从服务器返回的数据以及从request.html传过来的回调函数名传递给proxy.html。
接下来看看php代码以下,其实就是想返回一个json数据:
<?php $data = json_decode(file_get_contents("php://input")); header("Content-Type: application/json; charset=utf-8"); echo ('{"id" : ' . $data->id . ', "age" : 24, "sex" : "boy", "name" : "huangxueming"}'); ?>
最后就是proxy.html代码:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> </head> <body> <script> function _getUrl(key) {//通用方法,获取URL参数 var query = location.href.split("?")[1], value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]); return value; } (function() { var callback = _getUrl("callback"), data = _getUrl("data"); eval("window.top." + decodeURIComponent(callback) + "(" + decodeURIComponent(data) + ")"); })(); </script> </body> </html>
这里也是最后一步了,proxy终于拿到了request.html透过response.html传过来的回调函数名以及从response.html直接传过来的响应数据,
利用window.top执行request.html里定义的回调函数。
四:iframe高度自适应的问题。
iframe高度自适应分为2种,一种是同域下自适应 另一种是跨域下自适应,下面咱们来看看同域下iframe高度自适应的问题。
1. 同域下iframe高度自适应的问题:
思路:获取被嵌套iframe元素,经过JavaScript取得被嵌套页面最终高度,而后在主页面进行设置来实现。
假如咱们demo有iframe1.html和iframe2.html 下面贴上iframe1.html代码以下:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <iframe src="http://a.com/demo/ajax/iframeheight/iframe2.html" style="width:100%;border:1px solid #333;" frameborder="0" id="iframe"></iframe> <script> window.onload = function() { var iframeid = document.getElementById('iframe'); if(iframeid && !window.opera) { if(iframeid.contentDocument && iframeid.contentDocument.body.offsetHeight) { iframeid.height = iframeid.contentDocument.body.offsetHeight; }else if(iframeid.Document && iframeid.Document.body.scrollHeight){ iframeid.height = iframeid.Document.body.scrollHeight; } } } </script> </body> </html>
iframe2.html代码以下:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <div style="height:500px;"></div> </body> </html>
就能够动态设置iframe1页面的高度为iframe2的高度了。
2. 跨域下iframe高度自适应的问题。
首先咱们知道iframe跨域咱们是不能用上面js方式来控制了,因此咱们只能用个中间键,咱们能够在a.com域下iframe1.html页面嵌套一个b.com域下的iframe2.html页面,而后我在iframe2.html页面嵌套个和iframe1.html相同域的iframe3.html页面了,这样的话 iframe1.html和iframe3.html就能够无障碍的进行通讯了,由于页面iframe2.html嵌套iframe3.html,因此iframe2.html能够改写iframe3.html的href值。
iframe1中的内容:
iframe1.html内容主要接受iframe3.html页面传过来的内容而且去完成相应的操做。iframe1.html代码以下:
<iframe src="http://b.com/demo/ajax/iframeheight/iframe2.html" style="width:400px;height:200px;" id="iframe"></iframe> <script> var ifr_el = document.getElementById("iframe"); function getIfrData(data){ ifr_el.style.height = data+"px"; } </script>
iframe2.html中的内容:
iframe2.html内容是怎么把值传给iframe3.html页面,刚才说了是将值传递到iframe3.html页面的href中,因此只要修改iframe的src就能够,由于不用刷新C页面,因此能够用过hash的方式传递给iframe3.html页面.iframe2.html代码以下:
<!DOCTYPE HTML> <html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <iframe id="iframe" src="http://a.com/demo/ajax/iframeheight/iframe3.html" width="0" height="230px"></iframe> <script> var oldHeight = 0, ifr_el = document.getElementById("iframe"); t && clearInterval(t); var t = setInterval(function(){ var height = document.body.scrollHeight; if(oldHeight != height) { oldHeight = height; ifr_el.src += '#' +oldHeight; } },200); </script> </body> </html>
能够看到 默认状况下 iframe1.html 页面我给iframe2.html的高度是200像素, 可是在iframe2.html我给iframe3.html高度是230像素,那么正常状况下是有滚动条的,那么如今我是想在iframe2.html获取滚动条的高度,把高度传给经过iframe3.html的src里面去,而后在iframe3.html页面里获取这个高度值 传给iframe1.html(由于iframe1.html和iframe3.html是同域的),因此iframe1.html能取到这个高度值,再设置下自己的高度就是这个值就ok了。iframe3.html页面的惟一功能就是接收iframe2.html页面经过href传进来的值而且传递给iframe1.html页面,可到iframe2.html页面传来的值能够经过一个定时器不停去查看location.href是 否被改变,可是这样感受效率很低,还有个方式就是在新的浏览器中经过onhashchange事件 (IE8+,Chrome5.0+,Firefox3.6+,Safari5.0+,Opera10.6+)来监听href的改变。
iframe3.html代码以下:
<script> var oldHeight = 0; t && clearInterval(t); var t = setInterval(function(){ var height = location.href.split('#')[1]; if(height && height != oldHeight) { oldHeight = height; if(window.parent.parent.getIfrData) { window.parent.parent.getIfrData(oldHeight); } } },200); </script>
这样就能够解决经过跨域实现iframe自适应高度的问题了。
五:本地存储cookie,sessionStorage, localStorage比较及使用
一:Cookie
1. 什么是cookie?
Cookie是在客户端用于存储会话信息的,用户请求页面在web服务器与浏览器之间传递。每当同一台计算机经过浏览器请求某个页面时,就会发送这个 cookie。
2. cookie的限制?
1. Cookie的数据大小限制只能为4kb数据,若是数据长度超过4kb数据,超事后的数据将返回空字符串。
2. Cookie是以文件形式存储在客户端计算机中,查看和修改cookie很方便,可是安全性方面很差,所以重要的数据不要使用cookie来存储。
3. Cookie是有 有效期概念的,若是想要cookie存储多长时间,能够设置cookie的时间,通常的状况下,cookie的生命周期是在游览器关闭的时候失效。
4. Cookie是有域的概念的,在不一样的域下,cookie不能互相使用,cookie对于那个域是有效的,全部向该域发送的请求中都会包含这个cookie 的信息的,
这个值能够包含子域(subdomain 如www.zuixiandao.cn) ,也能够不包含它(如.zuixiandao.cn, 对于全部的zuixiandao.cn的全部子域都有效).
若是没有明确的指定,那么这个域会被认做来自设置cookie的那个域。
5. Cookie路径的概念:对于指定域中的那个路径,应该向服务器发送cookie,好比咱们能够指定cookie只有从http://www.zuixiandao.cn/books/中才能访问,那么http://www.zuixiandao.cn的页面就不会发送cookie信息。
6. Cookie失效时间的概念:表示cookie什么时候应该被删除,默认状况下,浏览器会话结束时即将删除全部的cookie,不过也能够本身设置
删除时间的。这个值是个GMT格式的日期(Wdy DD-Mon-YYYY HH:MM:SS GMT),用于指定应该删除cookie的准确时间,所以,
cookie可在浏览器关闭后依然保存在用户的机器上(同一个浏览器,不一样的浏览器不能保存),若是设置的日期是过时的日期,那么cookie马上删掉。
7. Cookie安全标志 指定后,cookie只有在使用SSL链接的时候才发送到服务器。好比:cookie信息只能发送给https://www.zuixiandao.cn,
而http://www.zuixiandao.cn的请求则不能发送cookie。
二: javascript中的cookie
1. Javascript中的cookie是 一系列由分号隔开的名-值对,以下面的淘宝的cookie,以下:
document.cookie = "isg=E5AA5F2CEE8AA93BB351D1601F7B218E; thw=cn; _med=dw:1920&dh:1080&pw:1920&ph:1080&ist:0; v=0; t=1292efa78d867ff6275e6c5cb971bed7";
2. 设置cookie的超时。
expires; // 设置cookie的过时的时间
如下设置 cookie 在 365天后超时;
var date = new Date();
date.setTime(date.getTime()+365*24*3600*1000);
document.cookie = ‘key:value;expires =' + date.toGMTString();
下面是设置cookie, 删除cookie,及 获取cookie的封装代码以下:
// 获取全部的cookies function getCookies() { var allCookies = document.cookie; return decodeURIComponent(allCookies); } // 获取指定的cookie function getOneCookie(name) { var allCookies = document.cookie.split(";"); for(var i = 0, ilen = allCookies.length; i < ilen; i++) { var temp = allCookies[i].split("="); if($.trim(decodeURIComponent(temp[0])) == name) { return decodeURIComponent(temp[1]); } } return -1; } // 添加cookie 有效期是一年 function addCookie(name,value,expires,path,domain,secure) { var curCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); if(expires instanceof Date) { curCookie += ';expires =' + expires.toGMTString(); }else { var date = new Date(); date.setTime(date.getTime()+365*24*3600*1000); curCookie += ';expires =' + date.toGMTString(); } if(path) { curCookie += "; path=" + path; } if(domain) { curCookie += "; domain=" +domain; } if(secure) { curCookie += "; secure"; } document.cookie = curCookie; } // 删除cookie function removeCookie(name,path,domain,secure) { addCookie(name,"",new Date(0),path,domain,secure); }
下面咱们来作一个小需求,好比一个登录页面,有 有户名,密码,记住密码,及显示cookie和删除cookie按钮。当我点击记住密码的时候,那么当我第重启开页面时候,只要输入用户名,密码会自动填充,固然咱们也能够点击删除cookie按钮进行删除,以下代码:
HTML代码:
<h2>cookie介绍</h2> <p> <label>用户名:</label> <input type="text" class="userName" id="userName"/> </p> <p> <label>密码:</label> <input type="password" id="password"> </p> <p> <label>记住密码:</label> <input type="checkbox" id="remember"/> </p> <input value="删除" type="button" id="delCookie">
<input type="button" value="显示cookie" id="showpassword">
JS代码以下:
<script> // 获取全部的cookies function getCookies() { var allCookies = document.cookie; return allCookies; } // 获取指定的cookie function getOneCookie(name) { var allCookies = document.cookie.split(";"); for(var i = 0, ilen = allCookies.length; i < ilen; i++) { var temp = allCookies[i].split("="); if(temp[0] == decodeURIComponent(name)) { return decodeURIComponent(temp[1]); } } return -1; } // 添加cookie 有效期是一年 function addCookie(name,value,expires,path,domain,secure) { var curCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); if(expires instanceof Date) { curCookie += ';expires =' + expires.toGMTString(); }else { var date = new Date(); date.setTime(date.getTime()+365*24*3600*1000); curCookie += ';expires =' + date.toGMTString(); } if(path) { curCookie += "; path=" + path; } if(domain) { curCookie += "; domain=" +domain; } if(secure) { curCookie += "; secure"; } document.cookie = curCookie; } // 删除cookie function removeCookie(name,path,domain,secure) { addCookie(name,"",new Date(0),path,domain,secure); } $("#userName").unbind('blur').bind('blur',function(){ var val = $(this).val(); if(val) { var curCookie = getOneCookie(val); if(curCookie != -1) { $("#password").val(curCookie); } } }); // 记住密码 $("#remember").unbind('click').bind('click',function(){ if(document.getElementById("remember").checked) { if($("#userName").val() && $("#password").val()) { addCookie($("#userName").val(),$("#password").val()); alert("Saved!"); } } }); // 删除cookie $("#delCookie").unbind('click').bind('click',function() { if($("#userName").val()) { removeCookie($("#userName").val()); alert(getCookies()); }else { alert("用户名为空"); } }); // 显示cookie $("#showpassword").unbind('click').bind('click',function(){ if($("#userName").val()) { var curCookie = getOneCookie($("#userName").val()); if(curCookie != -1) { alert(curCookie); }else { alert("没有cookie"); } }else { alert("没有cookie"); } }); </script>
三:IE用户数据;
在IE5.0中,微软经过一个自定义行为引入了持久化用户数据的概念,用户数据容许每一个文档最多128kb的数据,每一个域名最多1MB的数据,
要使用持久化数据,首先必须以下所示,使用css在某个元素上指定userData行为:
<div style="behavior:url(#default#userData)" id="dataStore">IE用户数据</div>
针对IE有以下使用方法:
1. getAttribute(“key”) 获取指定的属性值。
2. load(object) 从 userData 存储区载入存储的对象数据。
3. removeAttribute(“key”) 移除对象的指定属性。
4. save(object) 将对象数据存储到一个 userData 存储区。
5. setAttribute(“key”,”value”) 设置指定的属性值。
咱们继续作一个demo来演示下在IE浏览器下的存储的demo。
HTML代码以下:
<div style="behavior:url(#default#userData)" id="dataStore">IE用户数据</div> <input value="IE下保存数据" type="button" id="IESave"> <input type="button" value="IE下获取数据" id="IEGet"> <input type="button" value="IE下删除数据" id="IERemove">
JS代码以下:
var dataStore = document.getElementById("dataStore"); $("#IESave").click(function(e){ dataStore.setAttribute("name","tugenhua"); dataStore.setAttribute("book",'111111'); dataStore.save("bookInfo"); }); // IE下获取数据 $("#IEGet").click(function(){ dataStore.load("bookInfo"); alert(dataStore.getAttribute("name")); alert(dataStore.getAttribute("book")); }); // IE下删除数据 $("#IERemove").click(function(){ dataStore.removeAttribute("name"); dataStore.removeAttribute("book"); dataStore.save("bookInfo"); });
四:sessionStorage 和 localStorage
Html5新增了两个本地存储数据,分别是sessionStorage 和 localStorage.
浏览器支持程度以下:
注意:IE8 及 以上都支持 web storage。
sessionStorage: 将数据保存在session对象中,所谓session,指用户浏览某个网站时,从进入网站到浏览器关闭的这段时间,也就是用户浏览这个网站所花费的时间。
生命周期:指只在当前的窗口有效,打开一个新的同源窗口,或者说重启浏览器都失效。
数据大小:能够保存5MB甚至更多。
localStorage: 将数据保存在客户端本地的硬件设备(一般是指硬盘,但也能够是其余硬件设备),即便浏览器被关闭了,该数据依然存在,下次打开浏览器访问网站时仍然能够继续使用。可是,数据保存是按不一样的浏览器分别进行的,也就是说,若是打开别的浏览器,是读取不到在这个浏览器中保存的数据的。
生命周期:数据一直保存在硬盘中。持久性保存(可是不一样的浏览器保存的数据,是不能通用的)。
数据大小:能够保存5MB甚至更多的数据。
1. cookie 与 sessionStorage 及 localStorage的区别;
共同点:都是在客户端存储数据,且是同源的。
区别:
存储大小不同;cookie存储数据最大只能为4kb,而sessionStorage与localStorage能够保存5MB甚至更多数据。
Cookie数据始终在同源的http请求中携带,即cookie在浏览器与服务器之间来回传递,而sessionStorage与localStorage不会自动发给服务端,仅在本地保存。
数据有效期不一样;sessionStorage仅在当前浏览器窗口未关闭以前有效(同源的新窗口不生效),localStorage仅在当前的浏览器下永久生效(不一样的浏览器不能共享数据),无论关闭了 从新打开的 仍是生效的。Cookie只在设置的cookie过时时间以前一直有效,即便窗口或者浏览器关闭,或者打开新的同源窗口。
做用域不一样;sessionStorage不在不一样的浏览器窗口中共享,便是同一个页面,localStorage在全部的同源窗口中都是共享的(只在相同的浏览器下),cookie在全部的同源窗口都是共享的(仅在同一个浏览器中)。
SessionStorage与LocalStorage他们都拥有相同的方法;
1. setItem存储value
用法:.setItem( key, value),代码以下:
localStorage.setItem(key,value):将value存储到key字段
2. getItem获取value
用法:.getItem(key) 代码以下:
localStorage.getItem(key):获取指定key本地存储的值
3. removeItem删除key
用法:.removeItem(key),代码以下:
localStorage.removeItem(key):删除指定key本地存储的值
4. clear清除全部的key/value
用法:.clear(),代码以下:
localStorage.clear(); 清除全部的数据(firefox除外)
它将删除全部同源的本地存储的localStorage数据
而对于Session Storage,它只清空当前会话存储的数据。
sessionStorage也有上面同样的方法;
下面咱们来使用sessionStorage及 localStorage 来练习下,来作个demo。以下:
HTML代码以下:
<h1>web Storage实列</h1> <p id="msg"></p> <input type="text" id="input" /> <input type="button" value="保存数据" id="saveData"/> <input type="button" value="读取数据" id="readData"/> <input type="button" value="删除数据" id="removeData"/> <input type="button" value="清除全部的数据" id="clearData"/>
页面上一个input输入框,当我点击 保存数据 按钮后 分别使用sessionStorage和localStorage 把值保存起来,当我点击 读取数据 按钮后 读取数据,分别在不一样的浏览器或者新的同源窗口 或者关闭浏览器窗口 从新打开新窗口,来分别看看之间的区别,区别上面已经总结了,下面咱们来看看JS代码以下:
<script> // sessionStorage demo $("#saveData").unbind('click').bind('click',function(){ var inputVal = $("#input").val(); sessionStorage.setItem("message",inputVal); //localStorage.setItem("message",inputVal); }); $("#readData").unbind("click").bind('click',function(){ var msg = sessionStorage.getItem("message"); //var msg = localStorage.getItem("message"); $("#msg").html(msg); }); $("#removeData").unbind('click').bind('click',function(){ sessionStorage.removeItem("message"); //localStorage.removeItem("message"); }); $("#clearData").unbind('click').bind('click',function(){ sessionStorage.clear(); //localStorage.clear(); }); </script>
如上的代码,咱们如今继续来看看效果以下:使用
咱们还能够作一点复杂的应用,好比以下一个表格有一些字段,好比姓名,email,tel,及备注字段,咱们先保存到本地去,而后根据姓名这个字段进行搜索就能够搜索到数据到,咱们能够称为这是简单的本地数据库,以下代码:
<table> <tr> <td>姓名:</td> <td> <input type="text" id="name"/> </td> </tr> <tr> <td>EMALL:</td> <td> <input type="text" id="email"/> </td> </tr> <tr> <td>电话号码:</td> <td> <input type="text" id="tel"/> </td> </tr> <tr> <td>备注:</td> <td> <input type="text" id="memo"/> </td> </tr> <tr> <td>保存</td> <td> <input type="button" id="save" value="保存"/> </td> </tr> </table> <p> 检索:<input type="text" id="file"/> <input type="button" id="find" value="检索"/> </p> <p id="msg"></p>
JS代码以下:
// 保存数据 $("#save").unbind('click').bind('click',function(){ var data = new Object; data.name = $("#name").val(); data.email = $("#email").val(); data.tel = $("#tel").val(); data.memo = $("#memo").val(); var str = JSON.stringify(data); localStorage.setItem(data.name,str); alert("数据已经保存"); }); // 检索数据 $("#find").unbind('click').bind('click',function(){ var find = $("#file").val(); var str = localStorage.getItem(find); var data = JSON.parse(str); var result = "姓名:" + data.name + "</br>"; result += "Email: " + data.email + "</br>"; result += "tel:" + data.tel + "</br>"; result += "备注:" + data.memo + "</br>"; $("#msg").html(result); });
六:window.name 实现跨域数据传输。
Window.name 中的name值在不一样的页面(甚至不一样的域名)加载后依旧存在,而且数据量能够达到2MB。
Window.name 数据传输的基本原理:
同域下:Name在浏览器环境中是一个全局/window对象的属性,且当在ifrmae中加载页面时,name的属性值依旧保持不变。
好比咱们在同域下abc.example.com下 有2个页面 app.html 和 data.html
App.html页面代码嵌套一个iframe data.html页面,代码以下:
<iframe src="http://abc.example.com/demo/tugenhua0707/storage/data.html" id="iframe"></iframe>
其中data.html 页面 使用一个window.name = “111”;来保存数据。
如今咱们接下来在app.html页面 如何来调用同域下的data.html下的window.name的数据,首先咱们先要获取到这个iframe,而后判断iframe是否加载完,加载完后就获取这个iframe中的window.name,
App.html JS的代码以下:
function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } var iframe = document.getElementById("iframe"); // 同域下 iframeIsLoad(iframe,function(){ var data = iframe.contentWindow.name; alert(data); });
2. 跨域下:
如今咱们使用hosts文件来绑定2个IP 来演示下跨域的状况,在hosts文件绑定以下:
127.0.0.1 abc.example.com 和 127.0.0.1 def.example.com
咱们如今在 abc.example.com 新建一个app.html页面 里面仍是嵌套一个 def.example.com域下的 data.html页面,代码以下:
App.html代码以下:
<iframe src="http://def.example.com/demo/tugenhua0707/storage/data.html" id="iframe"></iframe>
若是咱们仍是和上面的方式取数据的话 明显报错跨域了,如今咱们是使用window.name解决跨域下数据的传输,那么咱们可使用一个同域abc.example.com下的代理页面proxy.html来作处理,经过在def.example.com域下的data.html页面加载一个与abc.example.com同域下的proxy.html页面, 将该目标页面设置iframe的name属性,由于app.html 与 proxy.html是在同一个域下,因此咱们能够获取到。
在app.html页面 JS代码以下:
function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } var iframe = document.getElementById("iframe"); var state = 0; // 跨域下 iframeIsLoad(iframe,function(){ if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 alert(data); //弹出111 } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://abc.example.com/demo/tugenhua0707/storage/proxy.html"; // 设置的代理文件 } });
固然如上:咱们若是name数据已经拿到了的话,之后不须要的话,咱们能够销毁掉,清空等操做。
七:使用HTML5中postMessage 实现ajax中的POST跨域问题
浏览器支持程度:IE8+,firefox4+,chrome8+ opera10+
1. 首先,要想接收从其余的窗口发过来的消息,就必须对窗口对象的message事件进行监听,以下代码:
window.addEventListener(“message”, function(){},false);
2. 其次,须要使用window对象的postMessage方法向其余窗口发送消息,该方法定义以下所示:
otherWindow.postMessage(message, targetOrigin);
该方法使用2个参数,第一个参数为所发送的消息文本,但也能够是任何javascript对象,第二个参数是接收消息的对象窗口的url地址
(好比:http:127.0.0.1:8080/) , 可是咱们也能够在url地址字符串中使用通配符”*”, 指定所有的域下,可是咱们仍是建议使用特定的域名下,
otherWindow为要发送窗口对象的引用。
Demo演示:
假如如今我在hosts文件下 ,绑定2 个域名以下:
127.0.0.1 abc.example.com
127.0.0.1 longen.example.com
如今假如在abc.example.com域下有一个abc.html页面,在longen.example.com域下有def.html页面,如今我是但愿这2个不一样域名下的页面
能互相通讯,abc.html代码以下:
<form> <p> <label for="message" style="color:red;font-size:24px;">给iframe子窗口发一个信息:</label> <input type="text" name="message" value="send" id="message" /> <input type="submit" value="submit" id="submit"/> </p> </form> <h4>目标iframe传来的信息:</h4> <p id="test">暂无信息</p> <iframe id="iframe" src="http://longen.example.com/webSocket/def.html" style="display:none"></iframe>
JS代码以下:
var win = document.getElementById("iframe").contentWindow; document.getElementById("submit").onclick = function(e){ e.preventDefault(); win.postMessage(document.getElementById("message").value,"http://longen.example.com"); } window.addEventListener("message",function(e){ e.preventDefault(); document.getElementById("test").innerHTML = "从" + e.origin + "那里传过来的消息:\n" + e.data; },false);
Def.html代码以下:
HTML代码:
<form> <p> <label for="message">给父窗口abc.html发个信息:</label> <input type="text" name="message" value="send" id="message" /> <input type="submit" /> </p> </form> <p id="test2">暂无信息。</p>
JS代码以下:
var parentwin = window.parent; window.addEventListener("message",function(e){ document.getElementById("test2").innerHTML = "从父窗口传来的域" +e.origin + ",和内容数据:" + e.data; parentwin.postMessage('HI!你给我发了"<span>'+e.data+'"</span>。',"http://abc.example.com"); },false);
当我点击abc.html页面后,能够看到效果以下,从def.html返回内容了。以下:
咱们须要知道以下几条信息:
1. 经过对window对象的message事件进行监听,能够接收消息。
2. 经过访问message事件的origin属性,能够获取消息的发送源。
3. 经过访问message事件的data属性,能够取得消息内容。
4. 使用postMessage方法发送消息。
5. 经过访问message事件的source属性,能够获取消息发送源的窗口对象(准确的说,应该是窗口的代理对象)。
有了上面的基本知识点,咱们能够延伸为实现ajax POST跨域的问题。
2. 使用postMessage 知识点解决 ajax中POST跨域问题。
原理:原理也很简单,假如咱们的域名abc.example.com下的abc.html页面须要发ajax请求(跨域,域名为longen.example.com)下,那么咱们仍是先跨页面文档的形式,和上面同样,咱们能够如今longen.example.com下 创建一个页面,好比叫def.html. 那么咱们如今仍是在 abc.html 页面嵌入一个隐藏域iframe src路径指向longen.example.com域下def,html页面。过程仍是和跨文档相似,
只是如今在def.html页面中 在window.onmessage 事件内写ajax请求便可,以下代码:
abc.example.com下的abc.html页面以下:
html代码和上面同样,下面是JS代码:
var win = document.getElementById("iframe").contentWindow; document.getElementById("submit").onclick = function(e){ e.preventDefault(); win.postMessage(document.getElementById("message").value,"http://longen.example.com/"); } window.addEventListener("message",function(e){ e.preventDefault(); alert(typeof e.data) var json = JSON.parse(e.data); console.log(json); alert(json.url) },false);
def.html代码以下:
JS代码以下:
//获取跨域数据 window.onmessage = function(e){ $.ajax({ url: 'http://longen.example.com/webSocket/test.php', type:'POST', dataType:'text', //data: {msg:e.data}, success: function(res) { var parentwin = window.parent; parentwin.postMessage(res,"http://abc.example.com");//跨域发送数据 } }); };
test.php代码以下:
<?php $data=array( url =>1, name =>'2', 'xx-xx'=>"xx" ); echo json_encode($data); ?>
如上实现方式 就能够实现ajax post跨域了。