前面咱們已經學習了js
基礎知識和一些簡單的特效,基本上已經可以寫出一個帶有特效的靜態頁面了,爲何還要稱之爲靜態頁面呢?由於網頁裏的數據都是寫死的,真正的工做中,咱們是要經過Ajax
技術,去後臺獲取數據的。因此在本篇文章,我會向你們介紹下什麼是Ajax
技術,而且它的實現原理是什麼。javascript
在學習
Ajax
以前,咱們首先須要知道什麼是服務器。
一、什麼是服務器?php
服務器的本質其實就是一臺電腦,不過它不像通常的電腦同樣擁有鼠標鍵、鍵盤、顯示器等輸入設備,它直接就是一個主機,裏面只有主板、硬盤、
cpu
、內存而且性能比通常計算機的性能更高,穩定性更強。
PC
,服務器性能更好、安全性更高、穩定性更強。IDC
(對氣候、能源、消防、建築、安保等要求。服務器外觀圖:css
二、服務器提供什麼服務html
根據需求的不一樣,服務器的種類也有所不一樣。
Web Server
)Mail Server
)Database Server
)FTP
服務器(FTP Server
)DNS Server
)三、服務器操做系統:前端
Windows Server
Linux
(Debian
,Ubuntu
,CentOS
,Fedora
)四、服務器的應用軟件:java
Web
服務器(又稱:http
服務器,主要提供文檔的瀏覽功能,文本、圖片、視頻、音頻)。mysql
IIS
(Windows
)Apache
Nginx
數據庫服務器jquery
SQL Server
Oracle
MySQL
客戶端: 經過網絡向服務器請求服務的計算機就是客戶端(手機、電腦);web
客戶端軟件: 在客戶端計算機上運行的與服務器通信的軟件就叫客戶端軟件;ajax
單機軟件: 在客戶端計算機上運行的不訪問網絡的軟件叫作單機軟件;
軟件開發架構分爲兩種,分別是C/S
架構和B/S
架構。
一、C/S架構:
C/S
,是Client
:(客戶端)和Server
(服務器)兩個單詞的簡寫,指的是客戶端應用程序與服務器端應用程序通信的軟件開發架構。
對於C/S
架構,最爲常見的例子就是網絡遊戲,好比LOL
,若是不聯網就沒法使用。
優勢:
缺點:
app
;二、B/S架構
B/S
,是Browser
:(瀏覽器)和Server
(服務器),兩個單詞的簡寫,指的是Web
瀏覽器與服務器端應用程序通信的軟件開發架構。
如今全部的網站都是B/S
架構,好比知乎、網易雲音樂、百度...,用戶只需使用瀏覽器就能訪問服務器;
優勢:
缺點:
一、IP地址
IP
地址是網絡上每一臺設備通信時的身份標識(就像身份證、手機號)。
IP
地址長什麼樣子呢?
192.168.10.10
好比,百度的IP
地址就是:
119.75.213.61
特殊的IP
地址-表明本機:
127.0.0.1
如何查看當前IP
地址?
打開命令行工具,直接輸入「ipconfig」 ipconfig 命令
二、域名
域名簡單的說,就是給IP
地址起一個容易記憶的名字(就比如人的名字同樣)例如百度的域名:www.baidu.com
。
由於IP
地址記憶起來很是不方便,因此平常生活中用戶經過域名來訪問服務器更加方便。
特殊的域名:localhost
(表明本機)。
三、DNS 服務器
什麼是DNS
?DNS
(Domain Name Server
),其實就是域名服務器。
輸入網址後的訪問流程(域名->DNS
->IP
地址)
查看域名與IP
地址的對應關係(ping
命令)
能夠用Hosts
文件讓本身的電腦變成一個屬於本身的DNS
服務器。
四、網絡端口(Port)
端口是指計算機與外界進行通信的數據出口(入口),每一個端口爲不一樣的應用傳輸不一樣數據。
端口號: 每個端口都有一個端口號。範圍是從0
到65535
。
端口號一般跟在IP
地址後面,用冒號分隔。例如:192.168.1.1:80
、www.jd.com:80
經常使用端口號: 80(HTTP)
、3306(MySQL)
、21(FTP)
。
查看本機被佔用的端口狀況(命令行輸入:netstat
)
五、數據庫
按照數據結構來組織、存儲和管理數據的倉庫,軟件開發行業通常指的是數據庫軟件,常見的有Oracle
、MySQL
等。
特色:
DBA數據庫管理員:
從事管理和維護數據庫管理系統(DBMS
)的相關工做人員的統稱。保證數據庫的穩定性、安全性、完整性和高性能。
Web
服務器上的文件資源。HTML
網頁、文本、圖片、視頻、音頻、Web
服務器程序等。AMP
,A:Apache
,M:MySQL
,P:PHP
一、Apache:
世界排名第一的服務器軟件,特色是:簡單速度快,性能穩定。
二、MySQL:
體積小、速度快、使用成本低,並且仍是開源。
三、PHP:
超文本預處理器,直接將代碼嵌入到HTML
文檔中執行,簡單易學,容易上手。
在本身的Windows
電腦上Web
服務器軟件 - Wamp
。
WampServer
:Wamp
就是Windows
、Apache
、Mysql
、PHP
集成安裝環境,即在window
下的apache
、
php
和mysql
的服務器軟件。PHP
擴展、Apache
模塊,開啓/關閉鼠標點點就搞定,不再用親自去修改
配置文件了,WAMP
它會去作。不再用處處詢問php
的安裝問題了,WAMP
一切都搞定了,這個軟件
在windows
平臺上使用的較多。
下載Wamp
:Wamp官網
安裝Wamp
:安裝的時候要區分版本(64
位,32
位),點擊下一步下一步。
注意:安裝目錄的路徑不能出現中文。
程序安裝成功以後,任務欄裏面的小圖標是綠色的話,說明安裝成功。
剛剛上面提到過,域名:localhost
和 IP
地址:127.0.0.1
均可以打開本地服務器:
當出現wamp
頁面的時候說明軟件安裝成功。
web
服務器沒有正常運行(測試web
服務器的端口號是否被佔用)64
位版本、32
位版本要分清Web
服務器軟件請先關閉一、基本功能使用:
修改語言 右擊任務欄中的軟件小圖標==> language
==> chinese
Web服務器的啓動、中止、運行: 左擊小圖標 (修改配置文件以後,必定要重啓服務器);
功能介紹:Apache
其中兩個配置文件後面可能須要修改,因此這裏須要知道在哪找到它們。
看下它的配置文件-httpd.conf
,其中 #
表示的是註釋的意思。
功能介紹:MySQL
看下它的配置文件-my.ini
,其中 ;
表示的是註釋的意思:
功能介紹:PHP Apache
是一個web
服務器,它自己是不能解析PHP
語言的,因此這裏也集成了一個PHP
解析器
看下它的配置文件-php.ini
,其中 ;
表示的是註釋的意思:
一、爲Web服務配置一個域名(僅限本機使用的域名)
找到C:\Windows\System32\drivers\etc\hosts
文件並修改
將本地的IP設置一個新的域名lxh.com
,重啓Wamp
服務器,在地址欄裏輸入lxh.com
就會跳轉到服務器頁面:
二、自定義Web服務器的根目錄
咱們能夠看到,當咱們輸入本地域名或者
IP
的時候,都會彈出來服務器的界面,假如我想要打開一個文件的時候怎麼辦呢?這時候咱們就須要配置服務器的根目錄,只要是在根目錄裏面的文件,均可以經過服務器打開。
查找並打開安裝目錄D:\wamp64\bin\apache\apache2.4.23\conf\extra\httpd-vhosts.conf
文件:
打開修改配置文件,其中ServerName
指的是域名,咱們能夠將第一步配好的本地域名地址寫上去;DocumentRoot D:/lxhAjax
和<Directory "D:/lxhAjax/">
是自定義Web服務器的根目錄爲D:/lxhAjax
文件夾
三、爲Web服務器配置虛擬主機(一臺Web服務器當多臺用)
在同一局域網下別人能夠經過你的IP
訪問你的Web
服務器文件夾。
httpd-vhosts.conf
文件中查找 Require local
Require local
改爲 Require all granted
不過建議你們不要這樣作,安全性不高,電腦裏面的東西會被別人看到。
四、注意事項
php5.6
如下版本要設置php
默認編碼,default_charset = UTF-8
,不然PHP
程序可能沒法正確顯示中文。httpd.conf
文件設置DocumentRoot
前,先檢查是否已經關閉了虛擬主機,不然可能致使設置無效。默認狀況下Wamp
服務器只能被本機訪問,若是向被局域網的其餘電腦訪問須要修改配置
httpd-vhosts.conf
文件中查找 Require local
Require local
改爲 Require all granted
ping
對方IP
#
」表示註釋網絡協議約定了網絡計算機之間數據的傳輸的方式、數據的格式等。
常見的網絡應用底層協議:
HTTP
、HTTPS
超文本傳輸協議FTP
文件傳輸協議SMTP
簡單郵件傳輸協議HTTP協議:
HTTP
即超文本傳輸協議,網站是基於HTTP
協議的,好比咱們在開發網站中常用css
、js
、圖片等等都是基於該協議傳輸的。
組成部分:
HTTP
協議是對請求(Request
)和響應(Response
)的報文內容進行了約束和規範。
請求: 客戶機向服務器發送數據
響應: 服務器向客戶機發送數據
發送並請求請求報文,接收響應報文,這種獲取數據的方式咱們稱之爲HTTP
協議。
請求是由客戶端發起,其規範格式爲:請求行、請求頭、請求主體。
一、請求行:
由請求方法、請求URL
和HTTP
協議及版本構成
GET /code/login.php?username=123&password=123 HTTP/1.1
POST /code/login.php HTTP/1.1
二、請求頭:
這裏設置的主要是一些信息,包含客戶端,服務器。
User-Agent
:瀏覽器的具體類型,如:User-Agent:Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20100101 Firefox/17.0
Accept
:瀏覽器支持哪些數據類型,如:Accept: text/html,application/xhtml+xml,application/xml;q=0.9;
Accept-Charset
:瀏覽器採用的是哪一種編碼,如:Accept-Charset: ISO-8859-1
Accept-Encoding
:瀏覽器支持解碼的數據壓縮格式,如:Accept-Encoding: gzip, deflate
Accept-Language
:瀏覽器的語言環境,如:Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Host
:請求的主機名,容許多個域名同處一個IP
地址,即虛擬主機。Host:www.baidu.com
Connection
:表示是否須要持久鏈接。Keep-Alive/close
,HTTP1.1
默認是持久鏈接,它能夠利用持久鏈接的優勢,當頁面包含多個元素時(例如Applet
,圖片),顯著地減小下載所須要的時間。要實現這一點,Servlet
須要在應答中發送一個Content-Length
頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream
,而後在正式寫出內容以前計算它的大小。如:Connection: Keep-Alive
Content-Length
:表示請求消息正文的長度。對於POST請求來講Content-Length必須出現。Content-Type
:WEB服務器告訴瀏覽器本身響應的對象的類型和字符集。例如:Content-Type: text/html; charset='gb2312'
Content-Encoding
:WEB
服務器代表本身使用了什麼壓縮方法(gzip,deflate
)壓縮響應中的對象。例如:Content-Encoding:gzip
Content-Language
:WEB
服務器告訴瀏覽器本身響應的對象的語言。Cookie
:最經常使用的請求頭,瀏覽器每次都會將cookie
發送到服務器上,容許服務器在客戶端存儲少許數據。Referer
:包含一個URL,用戶從該URL
表明的頁面出發訪問當前請求的頁面。服務器能知道你是從哪一個頁面過來的。Referer: http://www.baidu.com/
三、請求體:
這裏是提交給服務器的數據
須要注意的是,若是是往服務器提交數據,須要在請求頭中設置Content-Type:application/x-www-form-urlencoded
(在ajax
中須要手動設置);
響應報文是服務器發回給客戶端的。組成部分有狀態行,響應頭,響應主體。
一、狀態行:
由協議版本號、狀態碼和狀態信息構成
HTTP/1.1 200 OK
常見的狀態碼:
1XX
:信息狀態碼
100
Continue
繼續,通常在發送post
請求時,已發送了http header
以後服務端將返回此信息,表示確認,以後發送具體參數信息2XX
:成功狀態碼
200
OK
正常返回信息201
Created
請求成功而且服務器建立了新的資源202
Accepted
服務器已接受請求,但還沒有處理3XX
:重定向
301
Moved Permanently
請求的網頁已永久移動到新位置。302
Found
臨時性重定向。303
See Other
臨時性重定向,且老是使用 GET 請求新的 URI。304
Not Modified
自從上次請求後,請求的網頁未修改過。4XX
:客戶端錯誤
400
Bad Request
服務器沒法理解請求的格式,客戶端不該當嘗試再次使用相同的內容發起請求。401
Unauthorized
請求未受權。403
Forbidden
禁止訪問。404
Not Found
找不到如何與 URI 相匹配的資源。5XX
: 服務器錯誤
500
Internal Server Error
最多見的服務器端錯誤。503
Service Unavailable
服務器端暫時沒法處理請求(多是過載或維護)。二、響應頭:
Date
:響應時間Server
:服務器信息Last-Modified
:資源最後修改時間 由服務器自動生成ETag
:資源修改後生成的惟一標識,由服務器自動生成Content-Length
:響應主體長度Content-Type
:響應資源的類型三、響應主體:
即服務端返回給客戶端的內容;
Asynchronous Javascript And XML
(異步的Javascript
和XML
)。
思考:
咱們訪問一個普通網站時,當瀏覽器加載完HTML
、CSS
、JS
之後,網站就固定了,若是網站內容發生改變,必須刷新網頁後,才能看到更新內容。
Ajax概念:
在瀏覽器中,咱們可以不刷新頁面,經過Ajax
的方式去獲取一些新的內容。
Ajax
不是一門的新的語言,而是對現有技術的綜合利用。HTTP
協議的基礎上以異步的方式與服務器進行通訊。js
幫咱們預約義的一個異步對象XMLHttpRequest
來完成的AJAX
是一種用於建立快速動態網頁的技術。經過在後臺與服務器進行少許數據交換,AJAX
可使網頁實現異步更新。這意味着能夠在不從新加載整個網頁的狀況下,對網頁的某部分進行更新。
優勢:
缺點:
XMLHttpRequest
對象的支持度不足,存在兼容性;Ajax
幹掉了back
按鈕,即對瀏覽器後退機制的破壞;URL
直接訪問;Ajax應用場景:
Ajax 包含如下五個部分:
Ajax
並不是一種新的技術,而是幾種原有技術的結合體。它由下列技術組合而成。
CSS
和XHTML
來表示。DOM
模型來交互和動態顯示。XML
與XSLT
XMLHttpRequest
來和服務器進行異步通訊。javascript
來綁定和調用。傳統Web應用程序與Ajax Web應用程序對比:
主要的差異,其實不是JavaScript
,不是HTML/XHTML
和CSS
,而是採用了XMLHttpRequest
來向服務器異步的請求XML
數據。
同步:
異步:
XMLHttpRequest
能夠以異步方式的處理程序。Ajax
的原理簡單來講,就是經過XMLHttpRequest
對象來向服務器發送異步請求,從服務器得到數據,而後用javascript
來操做DOM
而更新頁面。其中最關鍵的一步就是從服務器得到請求數據。
一、建立XMLHttpRequest對象:
Ajax
的核心是XMLHttpRequest
對象,它是Ajax
實現的關鍵,發送異步請求、接受響應以及執行回調都是經過它來完成。
現代瀏覽器:
全部現代瀏覽器(IE7+
、Firefox
、Chrome
、Safari
以及Opera
)均內建XMLHttpRequest
對象。
var xhr = new XMLHttpRequest();
老版本IE:
老版本的Internet Explorer
(IE5 和 IE6)使用ActiveX
對象:
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
爲了應對全部的現代瀏覽器,包括IE5
和IE6
,請檢查瀏覽器是否支持XMLHttpRequest
對象。若是支持,則建立 XMLHttpRequest
對象。若是不支持,則建立ActiveXObject
:
兼容性處理:
var xhr = null; if(window.XMLHttpRequest){ // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xhr = new XMLHttpRequest(); }else{ // IE6, IE5 瀏覽器執行代碼 xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
XMLHttpRequest對象的屬性和方法:
二、準備請求,設置請求的url等參數:
首先經過open()
方法初始化XMLHttpRequest
對象,接受三個參數:
// 規定請求的類型、URL 以及是否異步處理請求。 xhr.open(method,url,async);
method: 表示的是請求類型的字符串,能夠是「GET
」或者「POST
」。
GET請求:
xhr.open("GET","demo.php",true);
POST請求:
xhr.open("POST","demo.php",true);
url: 第二個參數是要做爲請求發送目標的URL
。
async: 第三個參數是true
或false
,表示請求是以異步仍是同步的模式發出。(默認爲true
,通常不建議爲false
)
false
:同步模式發出的請求會暫停全部javascript
代碼的執行,直到服務器得到響應爲止,若是瀏覽器在鏈接網絡時或者在下載文件時出了故障,頁面就會一直掛起。true
:異步模式發出的請求,請求對象收發數據的同時,瀏覽器能夠繼續加載頁面,執行其餘javascript
代碼三、發送請求:
經過XMLHttpRequest
對象的send()
方法,向服務器發送請求。
xhr.send();
GET請求:
通常狀況下,使用Ajax
提交的參數多數是些簡單的字符串,能夠直接使用GET
方法將要提交的參數寫到open
方法的url
參數中,此時send
方法的參數爲null
或爲空。
// get請求是將數據拼接在url後面的 xhr.open("GET",demo.php?name=tsrot&age=24,true); xhr.send(null);
POST請求:
若是須要像HTML
表單那樣POST
數據,請使用setRequestHeader()
來添加HTTP
頭。而後在send()
方法中規定你但願發送的數據:
// post請求須要加一個請求頭,而且使用send方法將數據進行發送 xhr.open("POST",demo.php,true); xhr.setRequestHeder("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); xhr.send(...);
四、處理響應:
當服務器收到瀏覽器發送的數據後,會響應一個內容,由於不知道何時數據響應回來,因此提供了一個事件方法onreadystatechange
。每當readyState
改變的時候就會觸發onreadystatechange
事件,readyState
屬性:存有XMLHttpRequest
的狀態信息。
xhr.onreadystatechange = function(){ // 爲了保證數據完整回來,咱們通常會判斷兩個值 if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } }
onreadystatechange
:當處理過程發生變化的時候執行裏面的函數
readyState
:ajax
處理過程
0
:請求未初始化(尚未調用 open()
)。1
:請求已經創建,可是尚未發送(尚未調用 send()
)。2
:請求已發送,正在處理中(一般如今能夠從響應中獲取內容頭)。3
:請求在處理中;一般響應中已有部分數據可用了,可是服務器尚未完成響應的生成。4
:響應已完成;您能夠獲取並使用服務器的響應了。status
狀態碼屬性(詳見上面狀態碼類型):
200
:」OK
」404
: 未找到頁面responseText
:得到字符串形式的響應數據;
基本html結構:
<h3>簡單的Ajax實例聊天室</h3> <div class="chatbox"> <!-- 聊天記錄界面 --> <div class="messages"></div> <!-- 輸入界面 --> <div class="form"> <div class="input"><textarea></textarea></div> <div class="btn"> <input type="button" class="send" value="發送"> <input type="button" class="clear" value="清屏"> </div> </div> </div>
js部分:
// 1-發送按鈕註冊點擊事件 var send = document.querySelector(".send"); var clear = document.querySelector(".clear"); var messages = document.querySelector(".messages"); var textarea = document.querySelector(".input").children[0]; send.onclick = function() { // 1-獲取輸入的內容 動態建立一個p標籤 添加到 messages中 var p = document.createElement("p"); var content = textarea.value; if (content != "" && content.trim()) { p.innerText = content + ":Levi"; messages.appendChild(p); p.className = "self"; textarea.value = ""; } // 2-建立Ajax請求 var xhr; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xhr = new XMLHttpRequest(); } else { // IE6, IE5 瀏覽器執行代碼 xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open('post', 'chat.php', true); // post請求的時候,須要使用setRequestHeader()添加響應頭 xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); xhr.send("message=" + content); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { var reply = xhr.responseText; var p = document.createElement("p"); p.innerText = "網友:" + reply; p.className = "other"; messages.appendChild(p); } } } // 3-清屏按鈕 clear.onclick = function() { messages.innerHTML = ""; } // 4-回車鍵觸發發送按鈕 textarea.onkeydown = function(e) { e = window.event || e; if (e.keyCode == 13) { send.onclick(); e.preventDefault(); } }
PHP部分:
<?php header('Content-Type:text/html;charset=utf-8'); /*建立 對話的隊列 */ $message = array( '你好呀!', '幹嗎?', '我在睡覺。', '上課吧', '騙你的', ); /*隨機的取了一句話*/ /*array_rand 去某個數組的隨機索引*/ echo $message[array_rand($message)]; sleep(1); ?>
PHP
部分咱們能夠不用深究,只須要知道請求的數據message
,在php
裏其實就是一個隨機字符串。
效果圖:
在HTTP
協議中,全部數據最終的傳輸格式所有都是字符串。若是想要在HTTP
協議中傳輸一些複雜類型的數據,如數組、對象等,沒法直接實現。
後臺只有一個,可是開發語言卻有不少種,一種後臺格式的數據,如何適應所有開發語言的需求呢?因此須要一個統一的數據格式來在各個語言之間傳遞數據。
XML
(Extensible Markup Language
),可擴展標記語言。它也是一個標記語言,因此它裏面也是標籤,而且也有文檔聲明。
XML文件的基本格式:
<!-- 1-聲明文檔 version:版本 encoding:編碼 --> <?xml version = "1.0" encoding="UTF-8"?> <!-- 2-xml必需要有根節點 root--> <root> <!-- name age相對於對象 --> <name>Levi</name> <age>18</age> </root>
注意:
HTML
同樣雖然能夠描述和傳輸複雜數據,可是其解析過於複雜而且體積較大,因此實際開發已經使用不多了。
Ajax請求XML數據:
首先,新建一個XML
數據格式的文件-data.xml
:
<?xml version = "1.0" encoding="UTF-8"?> <root> <name>Levi</name> <age>18</age> </root>
新建一個PHP
文件-xml.php
:
<?php // 設置數據解析格式爲xml解析方式 header("Content-Type:application/xml"); // 將數據返回給前端 $xml = file_get_contents("data.xml"); echo $xml; ?>
在html
裏面經過Ajax
得到數據:
var xhr = new XMLHttpRequest(); xhr.open("get","xml.php"); xhr.send(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4 && xhr.status ==200){ console.log(xhr.responseXML); // 返回XML形式的響應數據 // DOM裏面的api在xml裏面一樣適用 console.log(xhr.responseXML.getElementByTagName("name")[0].innerHTML); // 打印 Levi } }
responseXML
:得到XML
形式的響應數據。
在Ajax
中獲取到XML
數據以後,須要經過xhr.responseXML
這個屬性來獲取數據,獲取數據的時候能夠直接使用DOM
提供的API
。responseText
也能夠獲取到數據,可是獲取到的是字符串,沒法經過dom
`api`來操做。
JSON
(JavaScript Object Notation
),是一種輕量級的數據交換格式,獨立語言。
json
有別於通常的對象,雖然json
也是鍵值對的存在,可是json
的鍵必需要加雙引號,而通常的js
對象能夠不用加。
json數據的基本格式:
data:[ { "name":"zs", "age":18, "skill":"吹牛" }, ... { "name":"ww", "age":28, "skill":"睡覺" } ]
Ajax請求json數據:
前面咱們知道了,前端在拿後臺數據的時候,對後臺數據處理提供了兩個方法,一個是對字符串處理的responseText
方法,還有一個是對XML
格式處理的responseXML
方法,可是惟獨沒有處理json
數據的方法,因此咱們須要藉助於json
內置對象的JSON.parse
方法,將後臺的返回的json
字符串,轉換成json
對象。
JSON.parse(xhr.responseText);
新建一個PHP
文件-json.php
:
<?php // 設置數據解析格式爲json格式 header("Content-Type:application/json"); $person = array('name' =>'Levi' ,'age'=>18,'skill'=>'帥' ); // json_encode 將對象數據轉換成json格式的數據返回前端 echo json_encode($person); ?>
在html
裏面經過Ajax
得到數據:
var xhr = new XMLHttpRequest(); xhr.open("get", "01-json.php"); xhr.send(); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { // 前端拿後臺數據的時候,只有兩種方式 responseText和responseXML // 沒有單獨爲json數據提供一個方法,因此須要將json字符串經過JSON.parse()方法,轉換成對象jianrong var jsonStr = xhr.responseText; var jsonObj = JSON.parse(jsonStr); console.log(jsonObj); // 打印的是一個對象 } }
總結方法:
將json
字符串,轉換成一個對象:JSON.parse(jsonStr);
// 注意,json字符串裏面的屬性必須是雙引號包裹,單引號包裹會報錯 var jsonStr = '{"name":"Levi","age":18,"skill":"帥"}'; var obj = JSON.parse(jsonStr); console.log(obj); // 打印對象 {name: "Levi", age: 18, skill: "帥"}
將對象轉換成json
格式的字符串:JSON.stringify;
var obj = { name: "Levi", age: "18", skill: "帥" }; var jsonStr = JSON.stringify(obj); console.log(jsonStr); //打印{"name":"Levi","age":"18","skill":"帥"}
一個頁面中,確定不僅是一處須要
ajax
請求,因此咱們能夠將它封裝成一個函數。
Ajax
對象獲取響應頭屬性:
xhr.getAllResponseHeaders(); // 獲取所有響應頭信息 xhr.getResponseHeader('key'); // 獲取指定頭信息
代碼封裝:
// 封裝前須要考慮的因素 // 1- 請求的方式 // get: 須要將數據拼接在url以後 // post: 須要加一個請求頭,而且使用send方法將數據進行發送 // 2- 請求的url地址 // 3- 須要發送的數據 // 4- 添加回調函數success,將請求到的數據返回給調用的函數 // 判斷服務器返回的是什麼格式的數據(經過響應頭) // a- xhr.getAllResponseHeaders(); 獲取所有響應頭信息 // b- xhr.getResponseHeader('key'); 獲取指定頭信息 function ajax(options) { // 默認值處理 // 設置默認的請求方式爲type options.type = options.type || "get"; // 設置默認的請求地址爲當前地址欄地址 options.url = options.url || location.href; // 設置默認的請求同步或者異步 options.async = options.async || "true"; // 設置請求參數data的默認值 options.data = options.data || {}; // 處理用戶傳進來的請求參數(data)對象 var dataArr = []; for (var k in options.data) { dataArr.push(k + "=" + options.data[k]); } var dataStr = dataArr.join("&"); // 異步請求對象兼容性處理 var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { // IE6及其如下版本 xhr = new ActiveXObjcet('Microsoft.XMLHTTP'); }; // 判斷當前的請求方式,若是是get,將數據拼接在地址後面 xhr.open(options.type, options.type == "get" ? options.url + "?" + dataStr : options.url, options.async); // 當是post請求的時候,須要設置請求頭 if (options.type == "post") { xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } // 發送數據,當是post方式的時候,發送數據 xhr.send(options.type == "get" ? null : dataStr); if (options.async) { xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { // 判斷請求的數據是什麼類型的 var type = xhr.getResponseHeader("Content-Type"); var result; if (type.indexOf("json") != -1) { // 若是是json格式的數據,就將其轉換成js對象 result = JSON.parse(xhr.responseText); } else if (type.indexOf("xml") != -1) { // 若是是xml格式的數據,直接返回responseXML result = xhr.responseXML; } else { // 若是兩種格式都不是,直接返回responseText result = xhr.responseText; } // 將處理好的數據進行傳遞 options.success(result); } } } else { // 若是是同步的話就不須要在監測狀態改變的狀況了 var type = xhr.getResponseHeader("Content-Type"); var result; if (type.indexOf("json") != -1) { result = JSON.parse(xhr.responseText); } else if (type.indexOf("xml") != -1) { result = xhr.responseXML; } else { result = xhr.responseText; } options.success(result); } } // 調用ajax請求 ajax({ url: "json.php", type: "get", data: {name: "levi",age: 18}, success: function(data) { console.log(data); } }); ajax({ url: "xml.php", type: "get", data: {name: "levi",age: 18}, success: function(data) { console.log(data); } });
前面的《jQuery
入門詳解》中已經講到了如何經過jQuery
操做Ajax
,這裏再爲你們總結一遍。
一、$.ajax()方式經常使用參數解析:
方法 | 做用 |
---|---|
url |
請求的地址 |
type |
請求的方式 |
dataType |
告訴jQuery ,須要按照什麼格式對服務器返回的數據進行解析,默認json |
data |
數據 |
success |
請求成功的回調函數 |
error |
請求失敗的回調函數 |
beforeSend |
請求發送以前調用的函數 |
complete |
不論請求是成功仍是失敗的,只要請求完成就會調用 |
timeout |
設置請求超時時間 |
示例代碼:
$.ajax({ // 請求的地址 url: "04-data.php", // 請求的方式 type: "get", // 告訴jQuery,須要按照什麼格式對服務器返回的數據進行解析,默認json dataType: "json", // 數據 data: { msg: "我是來請求數據的" }, // 請求成功的回調函數 success: function(data) { console.log(data); }, // 請求失敗的回調函數 error: function() { console.log("失敗了"); }, // 請求發送以前調用的函數 beforeSend: function() { console.log("請求發送以前調用的函數"); // 若是返回一個false,那麼就會阻止整個請求的發送 // return false; // 用法:能夠用做表單驗證,當表單內容符合規範的時候發送ajax請求,當不符合的時候就不發送ajax請求 }, // 不論請求是成功仍是失敗的,只要請求完成就會調用 complete: function() { console.log("請求完成了"); }, // 設置請求超時時間(單位:ms),超過這個時間後,就不會請求了 timeout:2000 });
二、jQuery中的serialize方法:
serialize
方法會將表單中全部的內容拼接成key=value&key=value
這樣的字符串。
經過這種方式就不要再去手動獲取表單中的內容的
<form id="form"> <input type="text" name="username"> <input type="text" name="pwd"> <input type="text" name="phonenumber"> <input type="text" name="email"> <button id="btn">獲取數據</button> </form> <script src="jquery.min.js"></script> <script> $(function() { $('#btn').click = function() { var dataStr = $('#form').serialize(); $.ajax({ url: "json.php", //data這個參數能夠接收對象,也能夠接受 key=value&key=value的這種字符串 data: dataStr, type: "post" }); } }); </script>
三、jQuery中的serializeArray方法:
上面的方法咱們能夠看到,獲取整個數據的時候,是很簡單,可是想要進行校驗的話就很難,由於上面的方法獲取的是一個字符串,不能進行校驗,因此此時咱們須要另一個方法,jQuery
中的serializeArray
方法。
<form id="form"> <input type="text" name="username"> <input type="text" name="pwd"> <input type="text" name="phonenumber"> <input type="text" name="email"> <button id="btn">獲取數據</button> </form> <script src="jquery.min.js"></script> <script> $(function() { $('#btn').click = function() { // 獲取到的數組拼接成字符串 var dataArr = $('#form').serializeArray(); $.ajax({ url: "json.php", data: dataArr, type: "post" }); } }); </script>
示例代碼:ajax模擬表單校驗及註冊
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>sing in page</title> <style> body { margin: 0; padding: 0; background-color: #F7F7F7; } ul { margin: 0; padding: 50px; list-style: none; } .register { width: 800px; margin: 50px auto; background-color: #FFF; border: 1px solid #CCC; border-radius: 5px; } li { display: flex; margin: 20px 0; } label, input { display: block; float: left; height: 46px; font-size: 24px; box-sizing: border-box; color: #333; } label { width: 200px; line-height: 46px; margin-right: 30px; text-align: right; } input { width: 320px; padding: 8px; line-height: 1; outline: none; position: relative; } input.code { width: 120px; } input.verify { width: 190px; margin-left: 10px; } input.disabled { background-color: #CCC !important; } input[type=button] { border: none; color: #FFF; background-color: #E64145; border-radius: 4px; cursor: pointer; } .error { color: red; margin-left: 10px; font-size: 12px; line-height: 46px; } .tips { position: fixed; top: 0; width: 100%; height: 40px; text-align: center; } .tips p { min-width: 300px; max-width: 400px; line-height: 40px; margin: 0 auto; color: #FFF; display: none; background-color: #C91623; } </style> </head> <body> <div class="register"> <form id="ajaxForm"> <ul> <li> <label for="name">用戶名</label> <input type="text" name="name" class="name" id="name"> <span class="error"></span> </li> <li> <label for="pass">請設置密碼</label> <input type="password" name="pass" class="pass" id="pass"> </li> <li> <label for="repass">請確認密碼</label> <input type="password" name="repass" class="repass" id="repass"> </li> <li> <label for="mobile">驗證手機</label> <input type="text" name="mobile" class="mobile" id="mobile"> </li> <li> <label for="code">短信驗證碼</label> <input type="text" name="code" class="code" id="code"> <input type="button" value="獲取驗證碼" class="verify"> </li> <li> <label for="submit"></label> <input type="button" class="submit" value="當即註冊" id="submit"> </li> </ul> </form> </div> <div class="tips"> <p>用戶名不能爲空</p> </div> <script src="../05-Form-Validation/js/jquery.min.js"></script> <script> /* * 1.獲取短信驗證碼 * 1.1 當沒有輸入手機號的時候 提示請輸入手機號 * 1.2 手機號格式不正確 提示請輸入正確的手機號 * 1.3 調獲取短信驗證碼接口 * 1.4 顯示正在發送中 不能再次發送(防止重複提交) * 1.5 當接口成功 按照後臺的計時時間 進行倒計時 * 1.6 當接口失敗 提示短信接口繁忙 恢復按鈕 * 1.7 倒計時完成以後 恢復按鈕 * */ /* * 2.註冊 * 2.1 當沒有輸入用戶名的時候 提示請輸入用戶名 * 2.2 調註冊接口 * 2.3 顯示正在提交 不能再次發送(防止重複提交) * 2.4 當接口成功 * 狀態碼 10000 成功 * 狀態碼 10001 失敗 提示用戶 用戶名已註冊 表單後 * 狀態碼 10002 失敗 沒輸用戶 請輸入用戶名 * 恢復按鈕 * 2.5 當接口失敗 恢復按鈕 * */ $(function() { /* 警告顯示提示 */ var showTip = function(tip) { $(".tips p").html(tip).fadeIn(500).delay(1000).fadeOut(500); }; /* 1.獲取短信驗證碼 */ $(".verify").on("click", function() { /* 當前按鈕指定變量 */ var $btn = $(this); /* 判斷當前按鈕是否有disabled屬性,有的話說明已經被點擊了,就不讓再點擊了 */ if ($btn.hasClass('disabled')) { return false; } /* 獲取手機號 */ var mobile = $.trim($('#mobile').val()); /* 判斷是否輸入內容,沒有的話提示信息 */ if (!mobile) { showTip('請輸入手機號'); return false; } /* 判斷手機格式 不正確的話提示信息 */ var regPhone = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/; if (!regPhone.test(mobile)) { showTip('請輸入正確的手機號'); return false; } /* 調取短信驗證碼接口 */ $.ajax({ url: 'registerCode.php', type: 'post', dataType: 'json', data: { mobile: mobile }, success: function(data) { if (data.code == 10000) { /* 給發送成功的按鈕添加一個倒計時 */ var time = parseInt(data.result.time); var timer = setInterval(function() { time--; $btn.val(time + '秒後再次獲取'); /* 倒計時完成以後 恢復按鈕*/ if (time <= 0) { $btn.val('獲取驗證碼').removeClass('disabled'); clearInterval(timer); } }, 1000); } else { /* 邏輯上的失敗 */ $btn.val('獲取驗證碼').removeClass('disabled'); } }, error: function() { /* 當接口失敗,提示短信接口繁忙 */ showTip('短信接口繁忙'); $btn.val('獲取驗證碼').removeClass('disabled'); }, beforeSend: function() { /* 點擊以後,顯示正在發送 */ $btn.val('正在發送...').addClass('disabled'); } }); $btn.addClass('disabled'); }); /* 2.註冊功能的實現 */ $('.submit').on('click', function() { /* 當前點擊的按鈕 */ var $btn = $(this); /* 正在請求當中 不能再次點擊 */ if ($btn.hasClass('disabled')) { return false; } var username = $("#name").val().trim(); var password = $("#pass").val().trim(); var repeatPassword = $("#repass").val().trim(); var code = $("#code").val().trim(); var phoneNum = $("#mobile").val().trim(); /* 調註冊接口 */ $.ajax({ type: 'post', url: 'register.php', data: { name: username, pass: password, repass: repeatPassword, code: code, mobile: phoneNum }, dataType: 'json', // beforeSend: function() { // /* 顯示正在提交 不能再次發送(防止重複提交)*/ // $btn.val('正在提交...').addClass('disabled'); // }, success: function(data) { /* 當接口成功 */ /* 狀態碼 10000 成功 */ if (data.code == 10000) { /* 提示+跳轉登陸頁 */ showTip('恭喜' + data.result.name + '註冊成功,3後秒自動前往登陸頁'); setTimeout(function() { location.href = 'http://www.baidu.com/'; }, 3000); } else if (data.code == 10001) { /* 輸入框提示 */ $('.error').html('用戶名已註冊'); /* 恢復按鈕 */ $btn.val('當即註冊').removeClass('disabled'); } else if (data.code == 10002) { showTip('請輸入用戶名'); /* 恢復按鈕 */ $btn.val('當即註冊').removeClass('disabled'); } }, error: function() { showTip('系統繁忙!'); $btn.val('當即註冊').removeClass('disabled'); } }) }); }); </script> </body> </html>
效果圖:
模板引擎,就是將一段已經寫好模板,使用數據進行填充以後生成
html
。
一、引入模板引擎插件:
<script src="template-web.js"></script>
二、建立script
標籤,注意類型是type="text/template"
,而且要有一個id
,模板內部是須要渲染的內容:
<script type="text/template" id="tpl"> <div>我叫 </div> <div>我今年 歲</div> </script>
三、調用template
方法,將數據渲染到模板內:
var obj = { name:"Levi", age:18 } // template("模板的id",要將什麼數據渲染到模板中) var html = template("tpl",obj);
四、回到上面的模板部分,在裏面添加佔位符:
<script type="text/template" id="tpl"> // {{}} ==> 就是佔位符 // name 和 age 對應的就是對象obj裏面的兩個屬性 <div>我叫{{name}}</div> <div>我今年{{age}}歲</div> </script>
五、打印調用的字符串:
var html = template("tpl",obj); console.log(html); // 打印的就是div字符串
一、$data:
模板一級特殊變量可使用
$data
,指的就是獲取的數據;
<!-- 能夠經過$data拿到 template函數傳進來的數據 --> {{$data["name"]}}
二、條件語句:
{{if value}}...{{/if}} {{if value1}}...{{else if value2}}...{{/if}}
示例:
<!-- 注意結束必需要有{{/if結尾}} --> {{if age >= 18}} <div>我成年了</div> {{else}} <div>我沒有成年了</div> {{/if}}
三、循環語句:
$index
指的是獲取當前遍歷的索引值;$value
指的是獲取當前遍歷的元素。
{{each target}} {{$index}} {{$value}} {{/each}}
示例:
<script type="text/template" id="tpl"> {{each idol}} <!--$index 獲取當前遍歷的索引--> <!--$value 獲取當前正在遍歷的元素--> <div>第{{$index}}號偶像:{{$value.name}}</div> {{/each}} </script> <script> var obj = { name: "Levi", age: 18, idol:[ {name : "劉德華"}, {name : "張學友"}, {name : "古天樂"} ] } var html = template("tpl", obj); // 引入jQuery $('body').append(html); </script>
效果圖:
注意:這裏介紹一個語法as v i
,能夠手動指定$index
和$value
的量
<script type="text/template" id="tpl"> {{each idol as v i}} <!--i 獲取當前遍歷的索引--> <!--v 獲取當前正在遍歷的元素--> <div>第{{i}}號偶像:{{v.name}}</div> {{/each}} </script>
四、變量:
<!--能夠在模板引擎中聲明變量--> {{set temp = data.content}}
示例:
<script type="text/template" id="tpl"> <!-- 設置一個變量val 用來接收數據的name值 --> {{set val = name}} <!-- 打印的就是對象的name屬性對應的值 --> {{val}} </script> <script> var obj = { name: "Levi", age: 18, idol:[ {name : "劉德華"}, {name : "張學友"}, {name : "古天樂"} ] } var html = template("tpl", obj); // 引入jQuery $('body').append(html); </script>
五、標籤「@」的用法:
當一個標籤在頁面以字符串形式顯示的時候,加上「
@
」後就會當成標籤去解析。
首先根據後臺數據,動態建立一個信息表格:
前端渲染:
<button id="btn">獲取數據生成表格</button> <script type="text/template" id="tpl"> <table width="600" border="1"> <thead> <tr> <th>姓名</th> <th>年齡</th> <th>性別</th> <th>頭像</th> </tr> </thead> <tbody> <!-- $data 是個一級變量,表示的就是返回的數據 --> {{each $data as v i}} <tr> <td>{{v.name}}</td> <td>{{v.age}}</td> <td>{{v.gender}}</td> <td>{{v.avatar}}</td> </tr> {{/each}} </tbody> </table> </script> <script src="template-web.js"></script> <script> $(function() { // 點擊按鈕,發送Ajax請求 $("#btn").click(function() { $.ajax({ url: "tableData.php", type: "get", success: function(data) { var htmlStr = template("tpl", data); $("body").append(htmlStr); } }); }); }); </script>
後臺數據:
<?php header("Content-Type:application/json;charset=utf-8"); echo '[{"name": "小喬", "age": 18, "gender": "male", "avatar": "<img src=\"1.jpg\" />"}, {"name": "大喬", "age": 18, "gender": "female", "avatar": "<img src=\"1.jpg\" />"}, {"name": "甄姬", "age": 18, "gender": "male", "avatar": "<img src=\"1.jpg\" />"}]'; ?>
根據上面的代碼,咱們能夠動態生成一個表格:
看到問題所在了,在後臺請求回來的圖片地址直接以字符串的形式渲染到頁面上了。
解決辦法:只須要在頭像佔位那一欄裏面加一個@
符號
{{each $data as v i}} <tr> <td>{{v.name}}</td> <td>{{v.age}}</td> <td>{{v.gender}}</td> <td>{{@v.avatar}}</td> </tr> {{/each}}
再看效果圖:
此時頭像就能夠顯示了。
一、原生語法:
<%= name %>
二、原生語法判斷語句:
<%= if(age == 18){ %> <div>我滿18歲了</div> <% } %>
三、原生語法循環語句:
<% for(var i = 0; i < arr.length; i++){ %> <!-- 遍歷數據數組arr,將它裏面的name屬性顯現出來 --> <div><%= arr[i].name %></div> <% } %>
json
數據模擬後臺數據:
{ "code": 200, "msg": "OK", "result": [{ "tc_id": "193", "tc_name": "一代天驕葫蘆娃", "tc_roster": "攻城獅", "tc_gender": "1", "tc_cellphone": "", "tc_email": "", "tc_status": "0", "tc_birthday": "1970-01-01", "tc_join_date": "2017-06-15" }, { "tc_id": "194", "tc_name": "用愛感化司馬ad", "tc_roster": "攻城獅", "tc_gender": "0", "tc_cellphone": "", "tc_email": "", "tc_status": "0", "tc_birthday": "1970-01-01", "tc_join_date": "1970-01-01" } ] }
html
頁面Ajax
請求部分:
<!-- 引入jQuery --> <script src="jquery.min.js"></script> <!-- 引入模板引擎 --> <script src="template-web.js"></script> <!-- 模板引擎渲染數據 --> <script type="text/template" id="tpl"> <table> <thead> <tr> <th>序號</th> <th>暱稱</th> <th>性別</th> <th>生日</th> <th>花名</th> </tr> </thead> <tbody> {{each $data.result as v i}} <tr> <!-- 序號從1開始,因此就是遍歷的下標加1 --> <td>{{i + 1}}</td> <!-- 暱稱 --> <td>{{v.tc_name}}</td> <!-- 後臺數據返回的是數字字符串。判斷下以男女顯示 --> <td>{{if v.tc_gender == "1"}}男{{else}}女{{/if}}</td> <!-- 生日 --> <td>{{v.tc_birthday}}</td> <!-- 花名 --> <td>{{v.tc_roster}}</td> </tr> {{/each}} </tbody> </table> </script> <script> $(function() { $.ajax({ url: "teacher.json", type: "get", success: function(data) { // 通常後臺都會提供接口文檔,能夠知道數據的名字,也能夠直接打印數據在控制檯中查看 console.log(data); // 當數據成功返回以後,將數據以表格的形式打印在頁面當中 if (data.code == 200) { var htmlStr = template("tpl", data); $('body').append(htmlStr); } } }); }); </script>
效果圖:
經過後臺提供的圖片信息,以及圖片連接,動態的生成瀑布流。
首先須要後臺提供的接口文檔:
接口地址:waterfull.php 請求方式:get 接口參數:page:當前是第幾頁 pageSize:當前頁面須要顯示數據的條數 返回類型:json 返回數據:{page: 2,items:[{path:"./images/0011.jpg",text:"文本信息"}...]} page:下一頁的頁碼 items:返回當前頁的數據 path:圖片地址 text:圖片下方的文本
後臺程序以及數據(僅攻參考,不是前端的活):
waterfull.php:
<?php header('Content-Type:text/html; charset=utf-8'); /*獲取數據 字符串*/ $data = file_get_contents('data.json'); /*轉化php對象? 須要對其操做*/ $data = json_decode($data); /*頁碼*/ $page = $_GET['page']; /*條數*/ $pageSize = $_GET['pageSize']; /*獲取數據的起始索引*/ $offset = ($page - 1) * $pageSize; /*slice 從什麼位子開始切割 切割多少條*/ $result = array_slice($data, $offset, $pageSize); /*下一頁的頁碼*/ $page++; /*轉化json字符串 輸出到前端*/ echo json_encode(array('page'=>$page, 'items'=>$result));/*{items:[]}*/ /*延時1秒返回數據*/ sleep(1); ?>
data.json:
[ { "path": "./images/001.jpg", "text": "一支素筆,一杯花茶,一段時光,淺笑又安然一場盛世的繁華,願不傾城,不傾國,只傾我全部。只爲過簡單安穩的生活,單純不平凡。一支素筆,一杯花茶,一段時光,淺笑又安然。早安!" }, ... { "path": "./images/100.jpg", "text": "青春,青春,一場盛世不平凡。一支素筆,一杯花茶,一段時光,淺笑又安然一場盛世的繁華,願不傾城,不傾國,只傾我全部。只爲過簡單安穩的生活,單純不平凡。一支素筆,一杯花茶,一段時光,淺笑又安然。早安!" } ]
Ajax請求後臺數據,動態渲染瀑布流:
Ajax請求數據:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>瀑布流</title> <style> body { margin: 0; padding: 0; font-family: "Microsoft Yahei"; background: #f5f5f5; } .box { width: 1200px; margin: 0 auto; padding-top: 40px } .box > .items { position: relative; } .box > .items > .item { width: 220px; box-shadow: 2px 2px 2px #999; position: absolute; } .box > .items > .item > p { margin: 0; padding: 10px; background: #fff; } /*目的是固定高度且不同*/ .box > .items > .item > img { width: 100%; display: block; height: px; } /*目的是固定高度且不同*/ .box > .items > .item:nth-child(4n) > img { width: 100%; display: block; height: 450px; } .box > .btn { width: 280px; height: 40px; margin: 30px auto; text-align: center; line-height: 40px; background-color: #CCC; border-radius: 6px; font-size: 24px; cursor: pointer; } .box > .loading { background-color: transparent; } </style> </head> <body> <div class="box"> <div class="items"> </div> <div class="btn">加載更多</div> </div> <script type="text/template" id="tpl"> {{each items as v i}} <div class="item"> <img src="{{v.path}}" alt=""> <p>{{v.text}}</p> </div> {{/each}} </script> <script src="jquery.min.js"></script> <script src="jquery.waterfull.js"></script> <script src="template-web.js"></script> <script> // ajax 請求,一進來先調用一次 function render(){ $.ajax({ url:"waterfull.php", type:"get", dataType:"json", data:{ // 3-首先去按鈕中,找下一頁的page屬性,若是沒有的話,給一個默認值1 page:$(".btn").data("page") || 1, pageSize: 15 }, success:function(data){ var htmlStr = template("tpl",data); $(".items").append(htmlStr); $(".items").waterfull(); // 1-將請求回來的數據中表示下一頁的頁碼page存入btn的自定義屬性data-page中 // 2-給按鈕加上一個自定義屬性page 值就是後臺返回的page屬性 // 7-當數據加載完以後,還要將按鈕變成正在加載,而且要移除disabled這個類 $(".btn").data("page",data.page).text("加載更多").removeClass("disabled"); // 8-數據是有限的,假如請求不到數據以後,須要將按鈕置成disabled,而且加上文字「沒有更多數據了」 if(data.items.length == 0){ $(".btn").text("沒有更多數據了").addClass("disabled"); } } }); } render(); // 4-點擊加載更多的時候,調用Ajax請求 $(".btn").click(function(){ // 6- 一進來縣普安段一下按鈕有沒有disabled這個類,若是有的話讓它不能夠被點擊 if($(this).hasClass("disabled")){ return false; } render(); // 5-點擊按鈕以後改變按鈕的狀態,和文本 $(this).text("正在加載中"); $(this).addClass("disabled"); }); </script> </body> </html>
其中jquery.waterfull.js
爲封裝的jQuery
瀑布流插件:
(function() { $.fn.waterFull = function() { //1. 肯定一共多少列 var columns = 5; //2. 獲取每個元素的寬度 var width = this.children().width(); //3. 計算間隔 var space = (this.width() - width * columns) / (columns - 1); //聲明數組來保存每一列當前的高度 var heightArr = []; this.children().each(function(index, ele) { //4. 爲第一行的元素設置定位 if (index < columns) { $(ele).css({ top: 0, left: index * (width + space), }); heightArr.push($(ele).height()); } else { //除過第一行以外的全部的內容 //先計算當前全部列中最短的列 var minHeight = heightArr[0]; var minIndex = 0; $.each(heightArr, function(index, value) { if (minHeight > value) { minHeight = value; //找到了最短的列所在的索引 minIndex = index; } }) //將當前要擺放的元素的高度累加到當前列所對應的高度中 heightArr[minIndex] += $(ele).height() + space; //就是最短列的高度加上間隔 var top = minHeight + space; //由於已經找到了要把當前元素放在哪一列 //因此直接使用列的索引計算便可 var left = minIndex * (width + space); $(ele).css({ top: top, left: left, }) } //5. 將items的高度設置爲最高的那一列的高度 var maxHeight = heightArr[0]; $.each(heightArr, function(index, value) { maxHeight = maxHeight > value ? maxHeight : value; }) console.log($(this)); $(this).parent().height(maxHeight) }); } })()
效果圖:
除了手動點擊按鈕以外,咱們還能夠監聽滾動條的位置,當在底部的時候直接調用加載函數:
$(window).scroll(function(){ // 獲取滾動條當前滾動的距離 var scrollTop = $(this).scrollTop(); // 獲取整個盒子的高度 var boxHeight = $(".box").outerHeight(); // 獲取可視區的高度 var windowHeight = $(window).height(); // 判斷當滾動條的高度大於等於盒子的高度減去可視區的高度的時候,調用加載函數 if(scrollTop >= boxHeight - windowHeight){ // 請求數據還須要判斷下有沒有disabled這個類,沒有的時候才能加載 if(!$(".btn").hasClass("disabled")){ render(); $(".btn").text("正在獲取數據").addClass("disabled"); } } });
Postman
是一款模擬Ajax
請求的軟件,根據接口文檔,輸入請求地址,以及選擇請求的方式,再輸入須要請求的數據,就能模擬從後臺,獲取到數據。
根據圖片的註釋,咱們能夠大體瞭解這款軟件的用法,根據接口文檔填上信息,點擊右上角send
,就會模擬發送Ajax
請求,response
返回請求的結果。
同源策略最初是在1995年時提出,到目前爲止全部瀏覽器都實行這個政策。
最初它的含義是指,A網頁設置的
Cookie
,B網頁不能打開,除非這兩個網頁"同源",所謂同源就是必需要知足三個條件:
舉個例子:
http://www.abc.com/home/index.html
這個網址中,協議是http://
,域名是www.abc.com
,端口是80
(默認端口能夠省略),下面看幾個例子:
URL | 說明 | 是否容許通訊 |
---|---|---|
http://www.a.com/a.html <br/>http://www.a.com/b.html |
協議、域名、端口都相同 | 容許 |
http://www.a.com/a/a.html <br/>http://www.a.com/b/b.html |
協議、域名、端口都相同,不一樣文件夾下 | 容許 |
http://www.a.com/a.html <br/>http://www.a.com:8000/b.html |
協議、域名相同,端口不一樣 | 不容許 |
http://www.a.com/a.html <br/>https://www.a.com/b.html |
域名、端口相同,協議不一樣 | 不容許 |
http://www.a.com/a.html <br/>https://www.b.com/b.html |
協議、端口相同,域名不一樣 | 不容許 |
http://www.a.com/a.html <br/>http://70.32.92.74/b.html |
協議、端口相同,域名和域名對應ip | 不容許 |
同源策略的目的就是爲了保護用戶信息安全,防止惡意的網站竊取數據。
打個比方,你登陸了某個網站A
,同時你又去瀏覽了另外一個網站B
,若是B
網站可以讀取你A
網站裏存儲的cookie
,會發生什麼?你在A
網站裏面的信息,將會被泄露,更可怕的是,cookie
每每用來保存用戶的登陸狀態,若是用戶沒有退出登陸,B
網站就能夠冒充用戶進行操做。因此「同源策略」是必須得。
隨着互聯網的發展,「同源策略」愈來愈嚴格。目前若是非同源,共有三種行爲受到限制:
(1) Cookie、LocalStorage 和 IndexDB 沒法讀取。 (2) DOM 沒法得到。 (3) AJAX 請求不能發送。
雖然這些限制是必要的,可是有時很不方便,合理的用途也受到影響。
同源策略規定,
Ajax
請求只能發給同源的網址,不然就報錯。
XHR
對象進行跨域請求會直接被瀏覽器制止html
一些標籤中的src
屬性也能夠發送請求,至關因而發送了一個get
請求src
屬性中書寫的地址,發送出去的請求,是不會受到瀏覽器同源策略的限制的下面介紹三種解決跨域的方法
JSONP
是服務器與客戶端跨源通訊的經常使用方法,最大的特色就是簡單適用。老式瀏覽器所有支持,服務器改造很是小。
實現原理:
jsonp
的原理就是:動態的建立一個script
標籤,將這個script
標籤的src
屬性設置爲要請求的地址url
,將script
標籤添加到頁面以後,src
屬性會自動向url
發送一個get
請求,又因爲,後臺返回的數據格式比較特殊,是一個函數調用的語句,因此咱們提早定義好一個函數,那麼這個函數就會在請求成功以後自動被調用,數據也會被傳入到這個函數中,最終就相似於ajax
請求的回調的效果!
<script> // url即請求的地址,賦值給動態建立的script標籤的src屬性 function creatScriptTag(url,callback){ // 一個頁面可能會有不少跨域請求,若是回調函數名寫死,那麼只能用一次 // 隨機生成一個函數名,將回調函數以這個隨機生成的名字命名 var callbackName = "jsonp" + new Data().getTime() + parseInt(Math.random() * 1000); // 將回調函數添加到window對象中,相似於添加了一個這個隨機函數名的一個全局函數 window[callbackName] = callback; var script = document.createElement('script'); script.setAttribute('type','text/javascript'); // 注意,該請求的查詢字符串有一個callback參數,用來指定回調函數的名字,這對於JSONP是必需的。 script.src = url + "?callback=" + callbackName; document.body.appendChild(script); } creatScriptTag("http://api.ajax.com/data.php", function(data){ console.log(data); }) </script>
jQuery裏的JSONP:
在jQuery
中,發送Ajax
方法的時候,只要定義一個dataType:"jsonp"
,便可實現跨域。
WebSocket
是一種通訊協議,正常是由後臺操控,使用ws://
(非加密)和wss://
(加密)做爲協議前綴。該協議不實行同源政策,只要服務器支持,就能夠經過它進行跨源通訊。
下面是一個例子,瀏覽器發出的WebSocket
請求的頭信息。
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
上面代碼中,有一個字段是Origin
,表示該請求的請求源(origin
),即發自哪一個域名。
正是由於有了Origin
這個字段,因此WebSocket
纔沒有實行同源政策。由於服務器能夠根據這個字段,判斷是否許可本次通訊。若是該域名在白名單內,服務器就會作出以下回應。
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
(本篇完)