Ajax相關(guān)總結(jié)

一技掏、 認(rèn)識Ajax

1、 初識 ajax

我們平常上網(wǎng)兴溜,不管是注冊賬號侦厚,還是瀏覽網(wǎng)頁,其本質(zhì)就是通過客戶端向服務(wù)器發(fā)送請求拙徽,服務(wù)器接到請求后返回處理后的數(shù)據(jù)給客戶端刨沦;
在我們之前學(xué)習(xí)代碼中,向服務(wù)器提交數(shù)據(jù)典型的應(yīng)用是就是 form 表單膘怕,其中的 action 就是我們提交數(shù)據(jù)的服務(wù)器端地址想诅;

完成一個 form 表單;
當(dāng)我們點(diǎn)擊提交按鈕時,頁面就會跳轉(zhuǎn)到服務(wù)器頁面侧蘸;

但是裁眯,我本不想讓頁面跳轉(zhuǎn),數(shù)據(jù)也能被發(fā)送到服務(wù)器端讳癌,同時穿稳,還可以接受服務(wù)器返回的數(shù)據(jù);

當(dāng)我注冊一個網(wǎng)站的賬號時晌坤,填寫完用戶名并沒有點(diǎn)擊提交逢艘,但是,用戶名如果有重復(fù)骤菠,文本框的傍邊便會提示我更換用戶名它改;

類似的功能還有 驗(yàn)證短信的發(fā)送、百度搜索的關(guān)鍵字推舉商乎、無刷新的分頁等等……

想要完成這些類似的功能實(shí)現(xiàn)央拖,我們今天所要學(xué)習(xí)的ajax技術(shù),就是核心技術(shù)鹉戚;

ajax 也是技術(shù)名詞的縮寫:
Asynchronous [?'s??kr?n?s; e?-] :異步的鲜戒;
JavaScript :JavaScript語言
And :和、與
XML :數(shù)據(jù)傳輸格式

1998年微軟公司(Microsoft)的Outlook Web Access第一次使用了ajax技術(shù)抹凳,允許客戶端腳本發(fā)送HTTP請求遏餐,并隨后集成在IE4.0中應(yīng)用(XMLHTTP),到2005年赢底,谷歌(Google)把Ajax成功應(yīng)用于自家的多款Web系統(tǒng)中(Gmail郵箱失都、Google Map、Google 搜索建議)幸冻,

從此Ajax被越來越多的人所接受…

客戶端通過HTTP向服務(wù)器發(fā)送請求

2粹庞、 快速入門

<body>
    <form action="1-1-1.php" method="get">
        <input type="text" name="names" value=""><br>
        <input type="button" value="提交">
    </form>
</body>
<script>
    //獲取DOM對象
    var inp = document.getElementsByTagName('input');
    //綁定點(diǎn)擊事件
    inp[1].onclick = function(){
        //獲取文本值
        var v = inp[0].value;
        //獲取ajax對象
        var xhr = new XMLHttpRequest();
        //監(jiān)聽狀態(tài)變化
        xhr.onreadystatechange = function(){
            //判斷狀態(tài)值
            if(xhr.readyState == 4){
                //獲取服務(wù)器返回信息
                alert(xhr.responseText);
            }
        }
        //打開鏈接
        xhr.open('get', '1-1-2.php');
        //發(fā)送連接
        xhr.send();
    }
</script>

1-1-2.php

echo 123;

二、 Ajax對象

1洽损、 獲取對象

通過上一節(jié)我們發(fā)現(xiàn)庞溜,想要使用 ajax 的一系列功能,我們就必須先得到 ajax 對象

基于 W3C標(biāo)準(zhǔn) 瀏覽器:

var xhr = new XMLHttpRequest();

基于IE內(nèi)核的瀏覽器:

var xhr = new ActiveXObject('Microsoft.XMLHTTP');
<script>
    var btu = document.getElementById('btu');
    btu.onclick = function(){
        //基于 W3C標(biāo)準(zhǔn) 瀏覽器
        var xhr = new XMLHttpRequest();
        alert(xhr);

        //基于IE內(nèi)核的瀏覽器趁啸, W3C標(biāo)準(zhǔn)瀏覽器中報錯
        var xhr = new ActiveXObject('Microsoft.XMLHTTP');
        alert(xhr);
    }
</script>

瀏覽器標(biāo)準(zhǔn)不一樣强缘,得到的對象也不一樣督惰,我們也不知道客戶使用什么樣的瀏覽器不傅,因此,我們需要解決兼容性問題赏胚;

修改上述代碼并測試访娶,具有兼容性

<script>
var btu = document.getElementById('btu');
btu.onclick = function(){
    try{
        var xhr =  new XMLHttpRequest()
    }catch(e){};

    try{
        var xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }catch(e){};

    alert(xhr);
}
</script>

再次對代碼進(jìn)行修改 兼容代碼封裝進(jìn)函數(shù)調(diào)用

<script>
    var btu = document.getElementById('btu');
    btu.onclick = function(){
        //封裝進(jìn)函數(shù)供其他程序調(diào)用
        function cXHR(){
            try{return new XMLHttpRequest()}catch(e){};
            try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){};
        }
        alert(cXHR());
    }
</script>

將函數(shù)寫入單獨(dú)的文件,共其他地方引入調(diào)用

創(chuàng)建createXHR.js
將函數(shù)復(fù)制到文件 createXHR.js 內(nèi)并保存觉阅,代碼如下:

function cXHR(){
    try {return new XMLHttpRequest()}catch(e){};
    try {return new ActiceXObject('Microsoft.XMLHTTP')}catch(e){};
}

使用:

//文件引入
<script src="createXHR.js"></script>
<script>
    var btu = document.getElementById('btu');
    btu.onclick = function(){
        //函數(shù)調(diào)用
        alert(cXHR());
    }
</script>

順便封裝一個方法:
使用id屬性獲取DOM對象崖疤,方便后面使用

function gid(id){
    return document.getElementById(id);
}

2秘车、 ajax對象的屬性、方法 *

火狐開發(fā)者文檔:
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

(1) 屬性

  • readyState: Ajax狀態(tài)碼
    0:表示對象已建立劫哼,但未初始化叮趴,只是 new 成功獲取了對象,但是未調(diào)用open方法
    1:表示對象已初始化权烧,但未發(fā)送眯亦,調(diào)用了open方法,但是未調(diào)用send方法
    2:已調(diào)用send方法進(jìn)行請求
    3:正在接收數(shù)據(jù)(接收到一部分)般码,客戶端已經(jīng)接收到了一部分返回的數(shù)據(jù)
    4:接收完成妻率,客戶端已經(jīng)接收到了所有數(shù)據(jù)
  • status :http響應(yīng)狀態(tài)碼
    200代表成功獲取服務(wù)器端數(shù)據(jù)
    404未找到頁面等等……
  • statusText :http響應(yīng)狀態(tài)文本
  • reponseText:如果服務(wù)器端返回字符串,使用responseText進(jìn)行接收
  • responseXML :如果服務(wù)器端返回XML數(shù)據(jù)板祝,使用responseXML進(jìn)行接收
  • onreadystatechange:當(dāng) readyState 狀態(tài)碼發(fā)生改變時所觸發(fā)的回調(diào)函數(shù)

(2)方法

  • open(method,url,async):初始化Ajax對象 (打開)
    method:http請求方式宫静,get/post
    url:請求的服務(wù)器地址
    async:布爾值,ture代表異步請求券时,false代表同步請求孤里;

  • setRequestHeader(header,value):設(shè)置請求頭信息
    header :請求頭名稱
    value :請求頭的值

  • xhr.getAllResponseHeaders() 獲取全部響應(yīng)頭信息

  • xhr.getResponseHeader('key') 獲取指定頭信息

  • send(content) :發(fā)送Ajax請求
    content : 如果是get請求時,此參數(shù)為null;如果是post請求時革为,此參數(shù)就是要傳遞的數(shù)據(jù)

    注意: 所有相關(guān)的事件綁定必須在調(diào)用send()方法之前進(jìn)行.

(3) 同步與異步

例如扭粱,小明去餐館排隊(duì)點(diǎn)餐,前臺服務(wù)員將小明的菜單告訴廚師進(jìn)行制作震檩,此時小明后面排隊(duì)的人就一直等著琢蛤,
直到廚師制作完成,把飯菜送到小明手里后離開抛虏,后面的人才能繼續(xù)點(diǎn)餐博其;這就是同步處理

但是,如果前臺服務(wù)員將小明的菜單告訴廚師后迂猴,服務(wù)員發(fā)給小明一個好牌去旁邊等待慕淡,后面的人繼續(xù)點(diǎn)餐,
廚師將小明的飯菜做好后沸毁,隨時呼喚小明就餐峰髓;這就是異步處理

服務(wù)器的不同做法,就代表著 Ajax 的同步或異步處理息尺;
小明就是客戶端携兵;
廚師就是后臺服務(wù)器;

PHP后臺代碼:

sleep(2);
$data = 't1';
echo $data;

前臺代碼:

<script src="createXHR.js"></script>
    <script>
        function t1(){
            var xhr = cXHR();
            xhr.onreadystatechange = function(){
                if(this.readyState == 4){
                    alert(this.responseText);
                }
            }
            //false同步
            //true 異步
            xhr.open('get', '02.php', false); 
            xhr.send(null);
        }
        function t2(){
            alert('t2');
        }
        t1();
        t2();
    </script>

三搂誉、 判斷用戶名是否可用--案例

前臺代碼

<body>
    <input type="text" value="" id="names"> 
    <span id="tip"></span>
</body>
<script src="createXHR.js"></script>
<script>
    var inp = gid('names');
    inp.onblur = function(){
        var xhr = cXHR();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                // alert(xhr.responseText);
                if(xhr.responseText == 1){
                    var h = '<font color="red">用戶名已經(jīng)被占用</font>';
                    gid('tip').innerHTML = h;
                }else{
                    var h = '<font color="green">用戶名可用</font>';
                    gid('tip').innerHTML = h;
                }
            }
        }
        xhr.open('get','03-1.php?names=' + inp.value);
        xhr.send();
    }
</script>

后臺PHP代碼

$v = $_GET['names'];
//鏈接數(shù)據(jù)徐紧,查詢是否存在用戶名 //此步驟省略

if($v == 'admin')
{
    echo 1;
}else
{
    echo 0;
}

四、 緩存問題

1、 緩存的產(chǎn)生

以上一節(jié)的案例為模板并级,使用IE瀏覽器測試拂檩;

$v = $_GET['names'];
//連接數(shù)據(jù),查詢是否存在用戶名
//此步省略
sleep(2);
if($v == 'admin')   //在瀏覽器輸入'zhangsan'嘲碧,和這里存的'admin'不一致稻励,所以顯示用戶可用
{
    echo 1;
}else
{
    echo 0;
}
$v = $_GET['names'];
//連接數(shù)據(jù),查詢是否存在用戶名
//此步省略
sleep(2);
if($v == 'zhangsan')    //'zhangsan'這個用戶名應(yīng)該是被占用的愈涩,但是在IE瀏覽器里卻是用戶可用
{
    echo 1;
}else
{
    echo 0;
}

原因:
在Ajax的get請求中钉迷,如果運(yùn)行在IE內(nèi)核的瀏覽器下,
其如果向同一個url發(fā)送多次請求時钠署,就會產(chǎn)生所謂的緩存問題糠聪。
緩存問題最早設(shè)計(jì)初衷是為了加快應(yīng)用程序的訪問速度,
但是其會影響Ajax實(shí)時的獲取服務(wù)器端的數(shù)據(jù)谐鼎。

2舰蟆、 客戶端解決緩存問題

產(chǎn)生緩存的問題就是 我們的客戶端向同一個 url 發(fā)送了多次請求;
如果我們每次請求的url不同狸棍,那么身害,緩存問題就不會存在了;

我們可以在請求地址的后面加上一個無意義的參數(shù)草戈,參數(shù)值使用隨機(jī)數(shù)即可塌鸯,
那么每次請求都會產(chǎn)生隨機(jī)數(shù),URL就會不同唐片,緩存問題就被解決了丙猬;

Math.random():返回 0--1 之間的隨機(jī)數(shù),包括 0 但不包括 1费韭;

修改代碼如下:

var url = '03-1.php?names=' + inp.value + '&_=' + Math.random();
xhr.open('get', url);

但是茧球,隨機(jī)數(shù)雖然解決了問題,但是星持,我們不能保證每次生成的隨機(jī)數(shù)都不一樣抢埋;
也就是說,使用隨機(jī)數(shù)存在一定的隱患督暂;

new Date().getTime() : 獲取當(dāng)前時間的毫秒時間戳
修改代碼如下:

var url = '03-1.php?names=' + inp.value + '&_=' + new Date().getTime();
xhr.open('get', url);

3揪垄、 設(shè)置響應(yīng)頭禁用客戶端緩存

服務(wù)器端在相應(yīng)客戶端請求時,可以設(shè)置相應(yīng)頭詳細(xì)逻翁,如:
header(‘Content-type:text/html; charset=utf-8’) :告訴客戶端瀏覽器饥努,使用utf-8的編碼格式解析頁面信息。

在php代碼中添加一下代碼:

//告訴客戶端瀏覽器不要緩存數(shù)據(jù)
header("Cache-Control: no-cache");

五卢未、 Ajax發(fā)送POST請求

1肪凛、 post請求

將之前寫過的 get 請求修改為 post 請求;

//請求地址
var url = '03-1.php';
//open參數(shù)為post
xhr.open('post', url);
//設(shè)置請求頭
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
//設(shè)置post請求參數(shù)值
xhr.send('names=' + inp.value);

ajax中g(shù)et請求與post請求的區(qū)別是:
1:傳參方式:
get請求在url尾部傳遞參數(shù)辽社;
post 請求在send()方法中傳遞參數(shù)

2:請求頭:
post 請求需要生命請求頭 xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
get 不需要設(shè)置伟墙;

3:參數(shù)值類型:
get 傳參值只能是數(shù)字、字符串
post 可以傳遞數(shù)字滴铅、字符串意外戳葵,還可以傳遞二進(jìn)制數(shù)據(jù);

2汉匙、Ajax 實(shí)現(xiàn)無刷新上傳文件

普通文件上傳拱烁,需要form表單,點(diǎn)擊上傳按鈕后噩翠,頁面會跳轉(zhuǎn):

HTML 代碼:

<form action="05.php" method="post" enctype="multipart/form-data">
    <input type="file" name="pic" > <br>
    <input type="submit" value="上傳" >
</form>

PHP后臺移動文件代碼:

//移動文件到新位置
move_uploaded_file($_FILES['pic']['tmp_name'], './' . $_FILES['pic']['name']);

上傳完成后戏自,我們在瀏覽器中打開調(diào)試工具可以看到結(jié)果。

文件上傳原理:

由此我們可以推斷伤锚,文件上傳的原理就是擅笔,瀏覽器客戶端將文件載入并解析為二進(jìn)制數(shù)據(jù),
然后通過HTTP協(xié)議將數(shù)據(jù)發(fā)送到服務(wù)器端屯援,文件上傳就已經(jīng)成功了猛们;
但是對于服務(wù)器來說,接收到的文件會放到系統(tǒng)緩存中狞洋,
我們需要使用PHP的move_uploaded_file函數(shù)將文件移至我們設(shè)置好的目錄下弯淘,并對緩存文件重新命名;
完成移動操作后吉懊,我們就可以在服務(wù)器端看見上傳后的文件了庐橙;

想要使用Ajax完成文件上傳,首先我們要學(xué)會借嗽,Ajax作為客戶端如何將文件讀入并解析為二進(jìn)制數(shù)據(jù)怕午;
HTML5為我們提供了 FormData 對象
通過FormData對象可以組裝一組用 XMLHttpRequest發(fā)送請求的鍵/值對。它可以更靈活方便的發(fā)送表單數(shù)據(jù)淹魄,因?yàn)榭梢元?dú)立于表單使用郁惜。
如果你把表單的編碼類型設(shè)置為multipart/form-data泵额,則通過FormData傳輸?shù)臄?shù)據(jù)格式和表單通過submit() 方法傳輸?shù)臄?shù)據(jù)格式相同;

FormData 手冊
https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects

<body>
    <form id="fm"  enctype="multipart/form-data" action="05.php" method="post">
        <input type="file" name="pic" > <br>
        <input type="submit" value="上傳" id="su">
    </form>
</body>
<script src="createXHR.js"></script>
<script>
    var fm = gid('fm');
    fm.onsubmit = function(){
        var xhr = cXHR();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                if(xhr.responseText == 1){
                    alert('上傳成功');
                }else{
                    alert('上傳失敗');
                }
            }
        }
        var url = '05.php';
        xhr.open('post', url);
        //FormData 會把表單的數(shù)據(jù)(包括文件流)憎亚,整體打包
        var fmdata = new FormData(this); 
        //發(fā)送整個FormData對象
        xhr.send(fmdata);
        //阻止提交跳轉(zhuǎn)
        return false;
    }
</script>

六、 Ajax與XML

Ajax請求后臺返回?cái)?shù)據(jù)時寇甸,都是簡單的字符串或數(shù)字缤沦;

如果后臺有大量數(shù)據(jù)要返回虎韵,我們應(yīng)該怎么辦?

目前有兩種技術(shù)方案:

1:將數(shù)據(jù)打包成 XML 的格式進(jìn)行傳輸

2:將數(shù)據(jù)打包成 json 的格式進(jìn)行傳輸

1缸废、 XML基本語法規(guī)則

XML 的語法規(guī)則很簡單包蓝,但很嚴(yán)格驶社。

XML 文檔必須有根元素
根元素是所有其他元素的父元素;

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

如上代碼测萎,root就是根元素亡电;

XML 聲明

<?xml version="1.0" encoding="utf-8"?>
聲明文件是可選部分,如果存在需要放在文檔的第一行;
version :版本號硅瞧,代表XML使用的版本號
encoding :編碼格式份乒,默認(rèn)UTF-8

所謂的文檔聲明就是告訴解析器當(dāng)前文檔格式、版本號以及編碼格式腕唧。

所有的 XML 元素都必須是成對閉合標(biāo)簽

非閉合標(biāo)簽是非法的或辖,解析器將報錯,不無正常解析枣接;

<user>
    <name>劉能</name>
    <!-- 錯誤的,無結(jié)束標(biāo)簽 -->
    <age>46
    <!-- 錯誤的,無開始標(biāo)簽 -->
    男</sex>
</user>

XML 標(biāo)簽對大小寫敏感

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <name>劉能</name>
    <!-- 錯誤颂暇,標(biāo)簽大小寫不一致 -->
    <Age>46</age>
    <sex>男</sex>
</user>

XML標(biāo)簽不允許有交叉嵌套
XML標(biāo)簽名不建議使用特殊字符,盡量只用數(shù)字字母下劃線

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <name>劉能</name>
    <age>46</age>
    <!-- 不建議使用 -->
    <s-ex>男</s-ex>
    <s.ex>男</s.ex>
</user>

2但惶、 PHP 解析XML

XML是一種數(shù)據(jù)傳輸格式蟀架,當(dāng)PHP接收到的數(shù)據(jù)就是一段XML的時候,我們的PHP應(yīng)該怎么處理XML數(shù)據(jù)呢榆骚?

在PHP5版本以后片拍,其提供了一個非常非常強(qiáng)大的類庫,SimpleXML類庫妓肢,專門用于實(shí)現(xiàn)對XML文檔的解析操作捌省。

解析原理

XML在解析時一共要經(jīng)歷三個步驟:

① 讀取XML文檔到內(nèi)存;

② 形成DOM樹結(jié)構(gòu)碉钠;

③ 生成SimpleXML對象纲缓。

SimpleXML類庫

user.xml

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <man>
        <name>劉能</name>
        <age>46</age>
        <sex>男</sex>
    </man>
    <man sex="男">
        <name>廣坤</name>
        <age>48</age>
    </man>
</user>

有user.xml 文件,內(nèi)容如上喊废,如何使用PHP解析呢祝高?
SimpleXML類庫提供了:

simplexml_load_file('xml_file_path')方法:
將XML文件解釋成一個對象

simplexml_load_string('xml_url_path')

將XML字符串解釋成一個對象

$xml = simplexml_load_file('user.xml');
var_dump($xml);

注意:
如果當(dāng)前讀取的節(jié)點(diǎn)是對象就通過->來進(jìn)行訪問。
如果當(dāng)前讀取的節(jié)點(diǎn)是數(shù)組就通過[]來進(jìn)行訪問污筷。

獲取XML數(shù)據(jù)中的所有name值

foreach循環(huán)遍歷:

$xml = simplexml_load_file('user.xml');
foreach ($xml -> man as $v)
{
    echo '姓名:' . $v -> name . '工闺;年齡:' . $v -> age . '<hr>';
}

for循環(huán)遍歷:

$xml = simplexml_load_file('./01.xml');
$length = count($xml);
for($i = 0; $i < $length; $i++)
{
    echo $xml -> man[$i] -> name;
}

3、 PHP 解析XML 案例

準(zhǔn)備一個有表單提交功能的HTML頁面瓣蛀,
輸入想要查詢的城市后陆蟆,點(diǎn)擊提交按鈕,將這個城市的天氣打印出來:

html代碼:

<form action="03.5.php" method="get">
    <input type="text" name="city"><br>
    <input type="submit" value="提交">
</form>

后臺PHP處理文件代碼:

//接受前臺提交的數(shù)據(jù)
$city = $_GET['city'];

//組裝請求地址
$url = 'http://v.juhe.cn/weather/index?cityname=' . $city . '&dtype=xml&format=&key=810c3b2c488bc37d5f521196d8799a72';

//發(fā)送請求并接受返回的數(shù)據(jù)
$s = file_get_contents($url);
// echo $s; //打印返回的XML數(shù)據(jù)

//使用 simplexml_load_string 函數(shù)讀入并解析XML數(shù)據(jù)
$xml = simplexml_load_string($s);

//找到并打印我們想要的數(shù)據(jù)
echo '城市:' . $xml -> result -> today -> city . '<hr>';
echo '氣溫:' . $xml -> result -> today -> temperature . '<hr>';
echo '天氣:' . $xml -> result -> today -> weather . '<hr>';
echo '著裝建議:' . $xml -> result -> today -> dressing_advice . '<hr>';

4惋增、PHP 生成XML

根據(jù)XML語法規(guī)則叠殷,使用PHP寫字符串即可;

PHP 代碼:

mysql_connect('localhost', 'root', '123456');
mysql_query('use test');
mysql_query('set names utf8');

//SQL 語句
$sql = "select * from test";
$res = mysql_query($sql);
//生成XML格式數(shù)據(jù)
$xml = '<users>';
while($row = mysql_fetch_assoc($res))
{
    $xml .= '<admin>';
    $xml .= '<id>' . $row['id'] . '</id>';
    $xml .= '<name>' . $row['name'] . '</name>';
    $xml .= '</admin>';
}
$xml . ='</users>';
//響應(yīng)頭聲明文件類型
header('Content-type:text/xml');
echo $xml;

5诈皿、 Ajax獲取XML數(shù)據(jù)

<body>
    <input type="button" value="獲取XML" id="su">
</body>
<script src="createXHR.js"></script>
<script>
    var fm = gid('su');
    fm.onclick = function(){
        var xhr = cXHR();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                //彈出獲取到的數(shù)據(jù)
                alert(xhr.responseText);
            }
        }
        var url = '06.php';
        xhr.open('post', url);
        //設(shè)置請求頭
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.send();
    }
</script>

此時林束,我們已經(jīng)能夠獲取到后臺返回的數(shù)據(jù)了像棘,但是,如果我想將 用戶名 全部取出并且展示到瀏覽器的界面中壶冒;
數(shù)據(jù)雖然接受到了缕题,但是,JS并沒有辦法解析使用這些數(shù)據(jù)依痊;

前面在介紹Ajax屬性時,有一個屬性是專門接受XML數(shù)據(jù)的:

responseXML :如果服務(wù)器端返回XML數(shù)據(jù)怎披,使用responseXML進(jìn)行接收

修改代碼胸嘁,使用responseXML接受數(shù)據(jù);

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        //彈出獲取到的數(shù)據(jù)(接受XML數(shù)據(jù))
        alert(xhr.responseXML);
    }
}

運(yùn)行代碼發(fā)現(xiàn)凉逛,我們得到的是一個XML的DOM對象性宏;

6、JS解析XML

非標(biāo)準(zhǔn)模型中状飞,鍵與值被解析為一個節(jié)點(diǎn)毫胜;
標(biāo)準(zhǔn)模型中,鍵與值被解析為上下級兩個節(jié)點(diǎn)诬辈;

標(biāo)準(zhǔn)模型在獲取到相應(yīng)的節(jié)點(diǎn)值還需要進(jìn)一步獲取其子節(jié)點(diǎn)酵使,然后才能獲取到其值。

修改上述代碼焙糟,完成功能口渔,將所有 用戶名 展示到瀏覽器界面

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        //接受XML數(shù)據(jù)
        var x = xhr.responseXML;
        var admin = x.getElementsByTagName('admin');
        for(var i = 0; i < admin.length; i++){
            //標(biāo)準(zhǔn)DOM解析查找方式
            var user = admin[i].
            getElementsByTagName('name')[0].
            childNodes[0].
            nodeValue;
            //將數(shù)據(jù)放入id為d的div標(biāo)簽中
            gid('d').innerHTML += user + '<br>';
        }
    }
}

小技巧:仔細(xì)思考發(fā)現(xiàn),不管DOM樹是否標(biāo)準(zhǔn)穿撮,都是DOM樹

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        //接受XML數(shù)據(jù)
        var x = xhr.responseXML;
        var admin = x.getElementsByTagName('admin');
        for(var i = 0; i < admin.length; i++){
            var user = admin[i].
            getElementsByTagName('name')[0].innerHTML;//不管DOM樹是否標(biāo)準(zhǔn)缺脉,都是DOM
            gid('d').innerHTML += user + '<br>';
        }
    }
}

JS如何操作HTML的DOM,就如何操作XML的DOM悦穿;

七攻礼、 Ajax與json

XML之所以應(yīng)用廣泛,就因?yàn)閄ML數(shù)據(jù)結(jié)構(gòu)化明確栗柒,適合大數(shù)據(jù)傳輸礁扮;
但是,在PHP中生成XML數(shù)據(jù)時瞬沦,需要我們填寫很多成對標(biāo)簽深员,然后聲明響應(yīng)頭為XML;
而在JS解析時蛙埂,也要進(jìn)行DOM節(jié)點(diǎn)的遍歷查找倦畅;

而字符串,沒有結(jié)構(gòu)化绣的,容易造成混亂叠赐,無法完成大量數(shù)據(jù)的傳輸欲账;
難道,我們就不能創(chuàng)造一種具有結(jié)構(gòu)明確的字符串格式嗎芭概?

生成和解析簡單赛不,易讀且結(jié)構(gòu)化明確,適合大數(shù)據(jù)傳輸?shù)淖址Y(jié)構(gòu):JSON

{"name":"劉能", "age":"45", "height":172}
[
    {"name":"劉能", "age":"45", "height":172},
    {"name":"大腳", "age":"43", "height":168},
    {"name":"趙四", "age":47, "height":175}
]

1罢洲、 什么是JSON

JSON 指的是 JavaScript 對象表示法(JavaScript Object Notation)
JSON 是輕量級的文本數(shù)據(jù)交換格式
JSON 獨(dú)立于語言 *
JSON 具有自我描述性踢故,更易理解

注意:
JSON 使用 Javascript語法來描述數(shù)據(jù)對象,但是 JSON 仍然獨(dú)立于語言和平臺惹苗。
JSON 解析器和 JSON 庫支持許多不同的編程語言殿较。

JSON 其實(shí)就是長的和JS對象幾乎一樣的 字符串

2桩蓉、 PHP生成JSON & JS解析json

之前的案例中淋纲,后臺PHP從數(shù)據(jù)庫獲取到數(shù)據(jù)后,生成XML格式返回給前端院究,
修改第6章案例中PHP代碼洽瞬,使PHP生成json字符串:

mysql_connect('localhost', 'root', '123456');
mysql_query('use test');
mysql_query('set names utf8');

//SQL 語句
$sql = "select * from test";
$res = mysql_query($sql);
$data = [];
while($row = mysql_fetch_assoc($res))
{
    $data[] = $row;
}
//json_encode 轉(zhuǎn)為json字符串
echo json_encode($d);

修改之前的案例中前端代碼,使JS解析json字符串為數(shù)組對象:

<script src="createXHR.js"></script>
<script>
    var fm = gid('su');
    fm.onclick = function(){
        var xhr = cXHR();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                var d = xhr.responseText;
                //將json字符串解析為JS數(shù)組對象
                var f = JSON.parse(d);
                //循環(huán)數(shù)組
                for(var i = 0; i < f.length; i++){
                    //獲取對象值
                    var u = f[i].name;
                    gid('d').innerHTML += u +'<br>';
                }
            }
        }
        var url = '08-2.php';
        xhr.open('post', url);
        //設(shè)置請求頭
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.send();
    }
</script>

3业汰、 無刷新錄入系統(tǒng)--案例

前臺代碼

<body>
   姓名:<input type="text" value=""> <br>
   年齡:<input type="text" value=""> <br>
   性別:<input type="text" value=""> <br>
   <input type="button" value="提交" id="btu">
</body>
<script src="createXHR.js"></script>
<script>
    var btu = gid('btu');
    btu.onclick = function(){
        var inp = document.getElementsByTagName('input');
        //將數(shù)據(jù)存入JS對象伙窃;
        var ar = {"name":inp[0].value, "age":inp[1].value, "sex":inp[2].value};
        // console.log(ar);//打印并查看數(shù)據(jù)類型

        var jn = JSON.stringify(ar);//將JS對象轉(zhuǎn)為JSON字符串
        // console.log(jn);//打印并查看數(shù)據(jù)類型

        //Ajax 發(fā)送數(shù)據(jù)
        var xhr = cXHR();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                if(xhr.responseText == 1){
                    inp[0].value = '';
                    inp[1].value = '';
                    inp[2].value = '';
                    alert('錄入成功');
                }else{
                    alert('錄入失敗');
                }
            }
        }
        xhr.open('get', '08-3.php?data=' + jn);
        xhr.send();
    }
</script>

后臺PHP代碼

mysql_connect('localhost', 'root', '123456');
mysql_query('use test');
mysql_query('set names utf8');

//獲取前臺傳參
$json = $_GET['data'];
// echo $json;

//將JSON字符串解析為PHP對象
// $d = json_decode($json);
// $sql = 'insert into test(name, age, sex) values ("' . $d -> name . '",' . $d -> age . ',"' . $d -> sex . '")';

//將JSON字符串解析為PHP數(shù)組
$d = json_decode($json, true);
$sql = 'insert into test(name,age,sex) values ("' . $d['name'] . '",' . $d['age'] . ',"' . $d['sex'] . '")';
$res = mysql_query($sql);
if(mysql_insert_id() > 0)
{
    echo 1;
}else
{
    echo 0;
}

4、 知識點(diǎn)總結(jié)

(1) JS操作JSON

//JS數(shù)組轉(zhuǎn)JSON字符串
var arr = ['路飛', '索隆', '娜美', '喬巴', '羅賓'];
var s = JSON.stringify(arr);
//結(jié)果為 數(shù)組形式的 JSON 字符串 
console.log(s);

結(jié)果: ["路飛","索隆","娜美","喬巴","羅賓"]


//JS對象轉(zhuǎn)JSON字符串
var arr = {'name':"路飛", 'age':17, 'money':5, 'nature':'橡膠'};
var s = JSON.stringify(arr);
//結(jié)果為 對象形式的 JSON 字符串 
console.log(s);

結(jié)果:{"name":"路飛","age":17,"money":5,"nature":"橡膠"}


//對象形式的JSON字符串轉(zhuǎn)JS 
var arr = '{"name":"路飛", "age":17, "money":5, "nature":"橡膠"}';
var s = JSON.parse(arr);
//結(jié)果為 JS對象
console.log(s);

//數(shù)組形式的JSON字符串轉(zhuǎn)JS
var arr = '["路飛", "索隆", "娜美", "喬巴", "羅賓"]';
var s = JSON.parse(arr);
//結(jié)果為 JS 數(shù)組
console.log(s);

(2) PHP操作JSON

//數(shù)組格式的JSON字符串轉(zhuǎn)PHP
$d = '["路飛", "索隆", "娜美", "喬巴", "羅賓"]';
$s = json_decode($d);
//結(jié)果為 PHP 數(shù)組
var_dump($s);

結(jié)果:
array(5) { [0]=> string(6) "路飛" [1]=> string(6) "索隆" [2]=> string(6) "娜美" [3]=> string(6) "喬巴" [4]=> string(6) "羅賓" }


//對象格式的JSON字符串轉(zhuǎn)PHP
$d = '{"name":"路飛", "age":17, "money":5, "nature":"橡膠"}';
//結(jié)果為 PHP 對象
$s = json_decode($d);

//結(jié)果為 PHP 關(guān)聯(lián)數(shù)組
$s = json_decode($d, true);

var_dump($s);

結(jié)果:
object(stdClass)#1 (4) { ["name"]=> string(6) "路飛" ["age"]=> int(17) ["money"]=> int(5) ["nature"]=> string(6) "橡膠" }

array(4) { ["name"]=> string(6) "路飛" ["age"]=> int(17) ["money"]=> int(5) ["nature"]=> string(6) "橡膠" }


//PHP索引數(shù)組生成JSON
$arr = ["路飛", "索隆", "娜美", "喬巴", "羅賓"];
$jn = json_encode($arr);
//結(jié)果為 數(shù)組形式的 JSON 字符串
var_dump($jn);

結(jié)果:["路飛","索隆","娜美","喬巴","羅賓"]

//PHP關(guān)聯(lián)數(shù)字
$arrs = ['name' => '路飛', 'age' => 17, 'money' => 5, 'nature' => '橡膠'];

//PHP對象
class Hz{}
$arr = new Hz();
$arr -> name = '路飛';
$arr -> age = 17;
$arr -> money = 5;
$arr -> nature = '橡膠';

//PHP中關(guān)聯(lián)數(shù)組和對象样漆,生成的JSON字符串均為對象形式JSON
echo json_encode($arrs);
echo json_encode($arr);

(3) 總結(jié)

生成JSON:
JS 數(shù)組轉(zhuǎn)JSON為 數(shù)組形式JSON
JS 對象轉(zhuǎn)JSON為 對象形式JSON

PHP 索引數(shù)組轉(zhuǎn)JSON為 數(shù)組形式JSON
PHP 關(guān)聯(lián)數(shù)組轉(zhuǎn)JSON為 對象形式JSON
PHP 對象轉(zhuǎn)JSON為 對象形式JSON

解析JSON:

數(shù)組形式JSON轉(zhuǎn) JS數(shù)組
對象形式JSON轉(zhuǎn) JS對象

數(shù)組形式JSON轉(zhuǎn) PHP索引數(shù)組
對象形式JSON轉(zhuǎn) PHP對象
對象形式JSON轉(zhuǎn) PHP關(guān)聯(lián)數(shù)組(參數(shù)true)

函數(shù)及方法:

json_encode(): PHP轉(zhuǎn)JSON对供;
json_decode(data,[true]):JSON 轉(zhuǎn)PHP對象或關(guān)聯(lián)數(shù)組氛濒;

JSON.parse():JSON字符串轉(zhuǎn)JS
JSON.stringify():JS轉(zhuǎn)JSON

注意:
JSON就是字符串产场,各種編程語言都可以解析或生成的 字符串

八、 Ajax框架的封裝

如果一個頁面中有十幾個地方用到Ajax舞竿,那么我們需要寫十幾次open()京景、十幾次send()、十幾次獲取xhr對象骗奖;
代碼重復(fù)相當(dāng)多确徙,而凡是有代碼重復(fù)的地方,就有封裝的可能执桌;

創(chuàng)建新文件: ajax.js

1鄙皇、 餐前甜點(diǎn)

之前我們?yōu)榱朔奖闶褂茫庋b過使用指定 id 獲取DOM對象及獲取xhr對象仰挣;
我們對之前的代碼進(jìn)行一次修改伴逸,使其更加優(yōu)雅;

定義一個自調(diào)用匿名函數(shù)

(function(){
    //code……
})();

為什么 定義一個自調(diào)用匿名函數(shù)膘壶?
在實(shí)際項(xiàng)目開發(fā)中错蝴,如果一個項(xiàng)目同時引入了多個javascript框架洲愤,可能會產(chǎn)生命名的沖突問題,
如果使用自調(diào)用匿名函數(shù)來封裝javascript框架顷锰,所有變量處于封閉狀態(tài)柬赐,就可以避免這個問題。

封裝一個$函數(shù)官紫,用于獲取指定id的dom對象

(function(){
    //封裝$函數(shù)肛宋,獲取指定 id 的DOM對象并返回給調(diào)用者
    var $ = function(id){
        return document.getElementById(id);
    }
})();

我們在前臺代碼中引入并使用ajax.js

<body>
   <div id="d">div</div>
</body>
<script src="ajax.js"></script>
<script>
    alert($('d'));
</script>

出現(xiàn)了報錯,報錯原因: 函數(shù) $ 為局部變量束世;

讓 $ 局部變量全局化

(function(){
    //封裝$函數(shù)酝陈,獲取指定 id 的DOM對象并返回給調(diào)用者
    var $ = function(id){
        return document.getElementById(id);
    }
    //將局部變量 $ 復(fù)制給頂層window對象,使其成為全局變量
    window.$ = $;
})();

2良狈、 封裝get方法

ajax代碼我們都會寫后添,問題是:
如何把代碼放進(jìn)匿名函數(shù)中并且外部可以調(diào)用笨枯?

(function(){
    //封裝$函數(shù)薪丁,獲取指定 id 的DOM對象并返回給調(diào)用者
    var $ = function(id){
        return document.getElementById(id);
    }
    //將局部變量 $ 復(fù)制給頂層window對象,使其成為全局變量
    window.$ = $;

    //聲明gets方法
    var gets = function(url){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                alert(xhr.responseText);
            }
        }
        xhr.open('get', url);
        xhr.send();
    }
    //將局部變量 gets 復(fù)制給頂層window對象馅精,使其成為全局變量
    window.ajax_get = gets;
})();

這樣寫并沒有語法錯誤严嗜,也可以正常調(diào)用,但是洲敢,隨著功能的不斷增加漫玄,
我們的window對象也會被賦予各種各樣的值,最終還是會導(dǎo)致混亂压彭;

在JavaScript中一切都是對象

$ 也可以被當(dāng)作對象睦优,我們就可以將ajax函數(shù)賦值給 $;

(function(){
    //封裝$函數(shù)壮不,獲取指定 id 的DOM對象并返回給調(diào)用者
    var $ = function(id){
        return document.getElementById(id);
    }

    //聲明ajax函數(shù)汗盘,并復(fù)制給$;
    $.get = function(url){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                alert(xhr.responseText);
            }
        }
        xhr.open('get', url);
        xhr.send();
    }
    window.$ = $;
})();

前臺調(diào)用

<script>
    $.get('09-1.php');
</script>

3、解決獲取Ajax對象的兼容性

修改上節(jié)代碼:

//獲取Ajax對象
$.init = function(){
    try{return new XMLHttpRequest()}catch(e){};
    try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){};
}

//聲明ajax函數(shù)询一,并復(fù)制給$;
$.get = function(url){
    var xhr = $.init(); //調(diào)用init,獲取ajax對象
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            alert(xhr.responseText);
        }
    }
    xhr.open('get', url);
    xhr.send();
}

4隐孽、 獲取Ajax的返回值

前臺調(diào)用:

<script>
    var cb = function(msg){
        $('d').innerHTML = msg;
    }
    $.get('09-1.php', cb);
</script>

修改 ajax.js

$.get = function(url, callback){
    var xhr = $.init(); //調(diào)用init,獲取ajax對象
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            callback(xhr.responseText);
        }
    }
    xhr.open('get', url);
    xhr.send();
}

前臺調(diào)用修改:

<script>
    // var cb = function(msg){
    //     $('d').innerHTML = msg;
    // }
    $.get('09-1.php', function(msg){
        $('d').innerHTML = msg;
    });
</script>

5、 配合后臺獲取不同的返回值類型

修改 ajax.js

//聲明ajax函數(shù)健蕊,并復(fù)制給$;
$.get = function(url, callback, type=null){
    var xhr = $.init(); //調(diào)用init,獲取ajax對象
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(type == null){
                callback(xhr.responseText);
            }
            if(type == 'xml'){
                callback(xhr.responseXML);
            }
            if(type == 'json'){
                var t = JSON.parse(xhr.responseText);
                callback(t);
            }
        }
    }
    xhr.open('get', url);
    xhr.send();
}

前臺調(diào)用菱阵,代碼修改:

<script>
    $.get('09-1.php', function(msg){
        console.log(msg);
    }, 'json');
</script>

6、 仿百度搜索推舉--案例

后臺PHP模糊查找獲取數(shù)據(jù):

$v = $_GET['v'];
mysql_connect('localhost', 'root', '123456');
mysql_query('use test');
mysql_query('set names utf8');
//SQL 語句
$sql = "select * from test where name like '" . $v . "%'";
$res = mysql_query($sql);
$data = [];
while($row = mysql_fetch_assoc($res))
{
    $data[] = $row;
}
echo json_encode($data);

前臺請求遍歷數(shù)據(jù):

<body>
    <input type="text" id="key"><br>
    <div id="result"></div>
</body>
<script src="ajax.js"></script>
<script>
    //oninput 元素的值發(fā)生改變時觸發(fā)缩功。
    //該事件僅支持<input>晴及、<textarea> 元素
    $('key').oninput = function(){
        var v = this.value;
        $.get('09-6.php?v=' + v, function(msg){
            // console.log(msg);
            $('result').innerHTML = '';
            for(var i = 0; i < msg.length; i++){
                $('result').innerHTML += '<div>' + msg[i].name + '</div>';
            }
        }, 'json');
    }
</script>

7、 無刷新分頁

整體思路:
用戶點(diǎn)擊上一頁嫡锌、下一頁抗俄,點(diǎn)擊觸發(fā)事件脆丁,根據(jù)當(dāng)前頁碼,拼接ajax請求參數(shù)动雹,發(fā)送請求槽卫;
后臺接受請求及參數(shù),鏈接數(shù)據(jù)庫獲取數(shù)據(jù)胰蝠,處理數(shù)據(jù)后返回前臺歼培;
前臺接到數(shù)據(jù)后,刪除舊數(shù)據(jù)茸塞,遍歷添加新數(shù)據(jù)躲庄;

前臺代碼:

<body>
    <a href="#" onclick="s()">上一頁</a>
    <a href="#" onclick="x()">下一頁</a>
    <div class="">
        <table id="tb">
        </table>
    </div>
    <!--存儲當(dāng)前頁碼數(shù)據(jù) 隱藏 -->
    <input type="hidden" name="" value="1" id="h">
</body>
<script type="text/javascript" src="ajax.js"></script>
<script type="text/javascript">
    function pub(p){
        $.get('09-7page.php?page=' + p, function(msg){
            // console.log(msg);
            $("h").value = msg.p;//更改當(dāng)前頁碼數(shù)
            delete msg.p;//刪除舊數(shù)據(jù)
            //制作表格頭
            $("tb").innerHTML = '<tr><td>編號</td><td>內(nèi)容</td></tr>';
            //遍歷數(shù)據(jù)并展示
            for(var i = 0; i < 3; i++){
                var h = '<tr>';
                h += '<td>' + msg[i].id + '</td>';
                h += '<td>' + msg[i].name + '</td>';
                h += '</tr>';
                $("tb").innerHTML += h;
            }
        }, 'json');
    }
    //頁面加載完成,調(diào)用函數(shù)發(fā)送ajax 
    window.onload = function(){
        pub(0);
    }
    //上一頁
    function s(){
        pub(parseInt($('h').value) - 1); //當(dāng)前頁減一
    }
    //下一頁
    function x(){
        pub(parseInt($('h').value) + 1);//當(dāng)前頁加一
    }
</script>

后臺PHP代碼:

mysql_connect('localhost', 'root', '123456');
mysql_query('use test');
mysql_query('set names utf8');
//查詢SQL
//獲取數(shù)據(jù)總條數(shù)
$sql = "select count(*) as num from test";
$res = mysql_query($sql);
$row = mysql_fetch_assoc($res);
$count= $row['num'];//獲取數(shù)據(jù)總條數(shù)

$psize = 3; //設(shè)置每頁條數(shù)
//ceil 向上取整
$pcount = ceil($count / $psize);//最大頁碼數(shù)

//獲取get傳參钾虐,第幾頁數(shù)據(jù)
$page = isset($_GET['page']) ? $_GET['page'] : 0;
if($page < 1)
{ //頁碼小于1噪窘,則取1
    $page = 1;
}
if($page > $pcount)
{//頁碼大于最大數(shù),則去最大數(shù)
    $page = $pcount;
}

$offset = ($page - 1) * $psize; //計(jì)算查詢區(qū)間
$sql = "select * from test limit $offset, $psize";
$res = mysql_query($sql);
$data = [];
while ($row = mysql_fetch_assoc($res)) 
{
    $data[] = $row;
}
//返回當(dāng)前頁碼數(shù)
$data['p'] = $page;
echo json_encode($data);

九效扫、 跨域問題及解決方案

1倔监、 認(rèn)識jsonp

<script src="ajax.js"> </script>
<script>
    $.get('http://bbs.com/1.php', function(){});
</script>

ajax 請求的URL地址,不在當(dāng)前域名下菌仁,就會出現(xiàn):同源策略進(jìn)制讀取位于xxx的遠(yuǎn)程資源浩习。

同源策略,也叫跨域禁止策略济丘;
阻止從一個域上加載的腳本谱秽,獲取或操作另一個域上的資源;

但是摹迷,公司內(nèi)部系統(tǒng)的數(shù)據(jù)交互就無法進(jìn)行

而Web頁面上調(diào)用js文件時則不受是否跨域的影響
(不僅如此疟赊,我們還發(fā)現(xiàn)凡是擁有"src"這個屬性的標(biāo)簽都擁有跨域的能力,比如script峡碉、img近哟、iframe);
src 的能力就是把遠(yuǎn)程的數(shù)據(jù)資源加載到本地(圖片异赫、JS代碼等);

前臺代碼:

<script src="ajax.js"> </script>
<script>
    //提前寫好函數(shù)椅挣,調(diào)用函數(shù)需要傳參
    function cb(msg){
        console.log(msg);
    }
</script>
<!--src加載進(jìn)來的代碼就是一個JS的函數(shù)調(diào)用,cb函數(shù)調(diào)用  -->
<script src="http://bbs.com/1.php"></script>

后臺PHP代碼:

$arr = ['a' => 1, 'b' => 'san', 'c' => 'wu', 'd' => 4];
$str = json_encode($arr);
//返回字符串,JS代碼的函數(shù)調(diào)用
//要返回的數(shù)據(jù)作為函數(shù)傳參傳遞
echo "cb(" . $str . ")";

修改前后臺代碼塔拳,增加靈活性鼠证;

前臺代碼:

<script src="ajax.js"> </script>
<script>
    //提前寫好函數(shù),調(diào)用函數(shù)需要傳參
    function callback(msg){
        console.log(msg);
    }
</script>
<!--src加載進(jìn)來的代碼就是一個JS的函數(shù)調(diào)用,cb函數(shù)調(diào)用  -->
<!--地址get傳參靠抑,告知后臺函數(shù)調(diào)用名稱 -->
<script src="http://bbs.com/1.php?cb=callback"></script>

后臺PHP代碼:

$arr = ['a' => 1, 'b' => 'san', 'c' => 'wu', 'd' => 4];
$str = json_encode($arr);
//返回字符串量九,JS代碼的函數(shù)調(diào)用
//要返回的數(shù)據(jù)作為函數(shù)傳參傳遞
//接受參數(shù)拼接,作為函數(shù)調(diào)用名稱
echo $_GET['cb'] . "($str)";

2、 如何使用JSONP

<body>
   <input type="button" id="btu" value="點(diǎn)擊">
</body>
<script src="ajax.js"> </script>
<script>
    //提前寫好函數(shù)荠列,調(diào)用函數(shù)需要傳參
    function callback(msg){
        console.log(msg);
    }
    //動態(tài)添加script標(biāo)簽及src屬性
    $('btu').onclick = function(){
        var sc = document.createElement('script');
        sc.src = "http://bbs.com/2.php?cb=callback";
        document.getElementsByTagName('head')[0].appendChild(sc);
    }
</script>

就是在遠(yuǎn)程服務(wù)器上設(shè)法動態(tài)的把數(shù)據(jù)裝進(jìn)js格式的文本代碼段中类浪,供客戶端調(diào)用和進(jìn)一步處理;
在前臺通過動態(tài)添加script標(biāo)簽及src屬性肌似,表面看上去與ajax極為相似费就,但是,這和ajax并沒有任何關(guān)系川队;
為了便于使用及交流力细,逐漸形成了一種 非正式傳輸協(xié)議,人們把它稱作 JSONP 固额;

該協(xié)議的一個要點(diǎn)就是允許用戶傳遞一個callback參數(shù)給服務(wù)端眠蚂,
然后服務(wù)端返回?cái)?shù)據(jù)時會將這個callback參數(shù)作為函數(shù)名來包裹住JSON數(shù)據(jù),
這樣客戶端就可以隨意定制自己的函數(shù)來自動處理返回?cái)?shù)據(jù)了斗躏。

3逝慧、 跨域資源共享( CORS)機(jī)制

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

php代碼中添加一下header頭聲明:

Access-Control-Allow-Origin:* //域名,* 允許所有

php:(服務(wù)端代碼)

<?php
header('Access-Control-Allow-Origin:http://localhost'); 
echo 1;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啄糙,一起剝皮案震驚了整個濱河市笛臣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迈套,老刑警劉巖捐祠,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碱鳞,死亡現(xiàn)場離奇詭異桑李,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)窿给,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門贵白,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人崩泡,你說我怎么就攤上這事禁荒。” “怎么了角撞?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵呛伴,是天一觀的道長。 經(jīng)常有香客問我谒所,道長热康,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任劣领,我火速辦了婚禮姐军,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己奕锌,他們只是感情好著觉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惊暴,像睡著了一般饼丘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辽话,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天葬毫,我揣著相機(jī)與錄音,去河邊找鬼屡穗。 笑死贴捡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的村砂。 我是一名探鬼主播烂斋,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼础废!你這毒婦竟也來了汛骂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤评腺,失蹤者是張志新(化名)和其女友劉穎帘瞭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒿讥,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝶念,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芋绸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒殉。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖摔敛,靈堂內(nèi)的尸體忽然破棺而出廷蓉,到底是詐尸還是另有隱情,我是刑警寧澤马昙,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布桃犬,位于F島的核電站,受9級特大地震影響行楞,放射性物質(zhì)發(fā)生泄漏攒暇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一敢伸、第九天 我趴在偏房一處隱蔽的房頂上張望扯饶。 院中可真熱鬧,春花似錦、人聲如沸尾序。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽每币。三九已至携丁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兰怠,已是汗流浹背梦鉴。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揭保,地道東北人肥橙。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像秸侣,于是被迫代替她去往敵國和親存筏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1味榛、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_x閱讀 15,968評論 3 119
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5椭坚? 答:HTML5是最新的HTML標(biāo)準(zhǔn)。 注意:講述HT...
    kismetajun閱讀 27,422評論 1 45
  • 大圖比較慢 支持格式多 按鍵/手勢自定義少 http://forum.portableappc.com/viewt...
    南不圖閱讀 887評論 0 1