[乾貨]數據交互與本地存儲

數據交互與本地存儲javascript

閱讀目錄php

一:Iframe父頁面與子頁面之間的調用css

專業詞語解釋以下:html

    Iframe:iframe元素是文檔中的文檔。前端

    window對象: 瀏覽器會在其打開一個HTML文檔時建立一個對應的window對象。可是,若是一個文檔定義了一個或者多個框架html5

(即:包含一個或者多個frame或者iframe標籤),瀏覽器就會爲原始文檔建立一個window對象,再爲每一個iframe建立額外的window對象,這些額外的window對象是原始窗口的子窗口。java

contentWindow: 是指指定的iframe或者iframe所在的window對象。jquery

   1. 父頁面與子頁面之間的調用。web

如今咱們能夠慢慢作demo來分別講解下,假若有iframe父頁面爲 iframe1.html, 父頁面上有2個子頁面 分別爲iframe2.html 和 iframe3.html。ajax

父頁面iframe1.html代碼以下:

<!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代碼以下:

<!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>

Cookie的實例demo以下:

cookie的demo

三: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");
});

IE瀏覽器下的demo以下:

使用IE瀏覽器下查看效果 請點擊我!!

四: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>

如上的代碼,咱們如今繼續來看看效果以下:使用

sessionStorage效果請點擊:

使用localStorage效果請點擊:

咱們還能夠作一點複雜的應用,好比以下一個表格有一些字段,好比姓名,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);
  });

demo以下效果:

請點擊查看:

六: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跨域了。

相關文章
相關標籤/搜索