打算寫個ajax系列的博文,主要是寫給自己看,學習下ajax的相關知識和用法,以更好的在工作中使用ajax。
假設有個網站A,它有一個簡單的輸入用戶名的頁面,界面上有兩個輸入框,第一個輸入框包含在一個form表單里用來實現form提交,第二個輸入框是單獨的、沒有包含在form里,下面就用這兩個輸入框來學習下jQuery的ajax。
1,前端的html和javascript代碼
頁面html
1 <main style="text-align: center; margin: 200px auto;"> 2 <h2>輸入用戶名</h2> 3 <form class="" action="demo01.php" method="post" style="margin-bottom: 20px;"> 4 <input id="user-name" type="text" name="username" placeholder="請填寫您的用戶名"> 5 <input type="submit" name="submit1" value="form提交1" class="input"> 6 </form> 7 <input id="user-name2" type="text" name="username2" placeholder="請填寫您的用戶名"> 8 <input type="button" name="submit2" value="ajax提交2"> 9 <div class="box"> 10 11 </div> 12 </main> 13 14 <script src="../../js/jquery-3.1.0.min.js"></script> 15 <script src="demo01.js"></script>
頁面中引入的demo01.js代碼,注意此處實現的是一個簡單的GET請求。
1 $(function($) { 2 $('input[name=submit2]').on('click', function(e) { 3 let username = ''; 4 if ('' !== (username = $('#user-name2').val())) { 5 $.ajax({ 6 url: `demo0.php?name=${username}`, 7 dataType: 'json', 8 method: 'GET', 9 success: function(data) { 10 if (data.result == 1) { 11 $('.box').html(`<div>你的姓名${username}已成功保存。</div>`); 12 } 13 }, 14 error: function(xhr) { 15 // 導致出錯的原因較多,以后再研究 16 alert('error:' + JSON.stringify(xhr)); 17 } 18 }) 19 .done(function(data) { 20 // 請求成功后要做的工作 21 console.log('success'); 22 }) 23 .fail(function() { 24 // 請求失敗后要做的工作 25 console.log('error'); 26 }) 27 .always(function() { 28 // 不管成功或失敗都要做的工作 29 console.log('complete'); 30 }); 31 } 32 }); 33 });
jQuery的ajax()方法有兩種寫法,分別是: $.ajax(url [, settings]); 和 $.ajax([settings]); 兩種寫法都可以,感覺第一種方法適合用於參數較少的情況,比如,如果只是對一個url做一個簡單的請求,不對返回的數據、格式和錯誤有要求,只需要傳遞一個url參數就可以,那就可以用第一種寫法。上面的demo01.js中采用的是第二種寫法,下面解釋下參數和相關的函數。
(1)上面代碼中ajax()的參數
可以看到這里的參數類型都是javascript對象,即都是 o = {key: value}; 這種類型的數據。jQuery的文檔中規定了,這里的參數只能是PlainObject(對象類型的對象),不能是null、自定義的數組、或者像docement這種歸屬於某種執行環境(比如瀏覽器)屬於某種類型的對象。這里不太好說清楚,可以做個小試驗。在命令行里打開node repl,進行下測試:
1 > node 2 > typeof(null); 3 'object' 4 > typeof([]); 5 'object' 6 > typeof(document); 7 'undefined' 8 > typeof({}); 9 'object'
可以看到null、[](數組類型)、{}(對象類型)都是對象。因為在js中一切皆對象。而在交互式環境中,document則是未定義的一個變量,所以它的類型是undefined。如果在瀏覽器環境下測試下typeof(document),那么它的類型也是object。下面逐個解釋下代碼用到的參數:
url,要請求的url地址,它的值應該是包含url的字符串。
dataType,字符串。發出請求后,期望從服務器返回的數據類型。可以指定的類型有xml、html、script、json、jsonp、text。如果不指定,jquery會基於MIME做判斷,並會返回一個下面xml、json、script、html當中的一種類型。
method,字符串。HTTP請求方法,默認為GET,上面代碼中指定為POST。
success, Type: Function( Anything data, String textStatus, jqXHR jqXHR ) ,匿名函數。HTTP請求成功后要調用的函數,可以傳遞三個參數給它:從服務器返回的數據(如果上面指定了dataType,則服務器返回的數據類型需要與上面dataType指定的類型一致)、一個可以描述狀態的字符串textStatus、還有一個jqXHR對象。可以看到上面只傳遞了從服務器返回的數據data。
error, Type: Function( jqXHR jqXHR, String textStatus, String errorThrown ) ,匿名函數。HTTP請求失敗后要調用的函數,同樣也可以傳遞三個參數。
除了用到的這些參數,還有許多其他的如:async、dataFilter、mimeType等其他參數,不過現在的這個簡單的腳本還用不到那么多參數。
(2)“延遲加載函數”
上面代碼中 $.ajax().done().fail().always() jqXHR.done()、jqXHR.fail()、jqXHR.always()中分別可以添加deferred對象被解析、被拒絕、被解析或被拒絕這三種情況下的要處理的工作,比如添加個函數什么的。為什么能夠這么做呢,這要看$.ajax()返回了什么,它返回的是jqXHR對象(jquery版本大於1.5時)。這個對象實現了Promise interface(Promise機制,用來傳遞異步操作消息,代表了某個未來才會知道結果的事件)。這就允許在一次請求中添加多個回調函數,甚至可以在請求完成后添加回調函數。
標題“延遲加載”描述的不夠准確,但從效果上看是有延遲加載的效果。關於這個問題更詳細的解釋可以參考jQuery文檔中對jqXHR的解釋 或一位前端前輩的解釋jQuery的deferred對象詳解 。
2,后端運行在nginx服務器上的php代碼
后端的邏輯很簡單:我們把前端獲取的數據保存到名為data-demo01的文件中,保存成功則向前端返回一個1作為標志。
(1)前端ajax發起GET請求
如果前端的ajax發起的是一個GET請求,那么后端也比較好處理:
1 if (isset($_GET['name']) && !empty($_GET['name'])) { 2 $username = trim($_GET['name']); 3 if (file_put_contents('data-demo01', $username)) { 4 echo '{"result": 1}'; 5 }
6 }
(2)前端ajax發起POST請求
js代碼中需要修改下ajax()的url、method參數,並增加一個data參數,修改后如下:
1 // 相同的代碼省略 2 $.ajax({ 3 url: `demo01.php`, 4 dataType: 'json', 5 method: 'POST', 6 data: {"username": username}, 7 // 相同的代碼省略
因為用POST傳遞數據,所以去掉url中用來傳遞數據的參數,下面的data類型要與dataType一致,為json格式,然后將username作為值傳遞。
那么后端的代碼也就可以確定了:
1 if (isset($_POST['username']) && !empty($_POST['username'])) { 2 $username = trim($_POST['username']); 3 if (file_put_contents('data-demo01', $username)) { 4 echo '{"result": 1}'; 5 } 6 }
如果不出錯的話,效果應該是下面這樣然后查看下data-demo01,名字果然被保存了。
那么問題來了,如果出錯了呢?比如data-demo01文件不可寫,或者后台服務器返回的數據格式有錯誤,或者網絡出錯。那又該怎么處理呢?我現在也不太清楚,后續再研究吧。
完