2019年12月31日 星期二

jQuery 的 Ajax 捷徑函數測試

過去兩周終於把 Ajax 的低階 Ajax 函數 $.ajax() 以及工具函數 (utilities) 的測試筆記寫完, 特別是對 $.ajax() 這個低階 Ajax 函數進行了完整的測試, 對於 url 與 data 的參數攜帶方式與 type 屬性值如何影響 Ajax 引擎發出的 HTTP 請求以及後端要如何捕捉參數有了清楚的了解, 參考 :

測試 jQuery 的 Ajax 函數 $.ajax()

結論摘要如下 :
  • type 屬性值 GET/POST 決定了 HTTP 要求是 GET/POST.
  • 若 type 是 GET, 不論參數是放在 url 查詢字串還是 data 屬性中, 一律轉成查詢字串附在 URL 中傳遞, 後端須用 $_GET[] 讀取.
  • 若 type 是 POST, 則放在 url 屬性中的參數以查詢字串附在 URL 中傳遞, 後端須以 $_GET[] 讀取; 放在 data 的參數不論是查詢字串或物件形式, 一律放在 HTTP 的 BODY 中傳遞, 後端須以 $_POST[] 讀取.
雖然 PHP 還提供了一個 $_REQUEST[] 函數可用來捕捉所有前端傳遞之參數, 無需理會前端是用 URL 查詢字串或 HTTP BODY 方式傳送, 但這個測試對於了解 jQuery 的 Ajax 操作還是很有用.

本篇繼續測試與 Ajax 操作相關的 jQuery 工具函數如下 :
  • $.get() 函數
  • $.post() 函數
  • $.getJSON() 函數
  • $.getScript() 函數
其實這些函數是 jQuery 以 $.ajax() 為基礎封裝的捷徑 (shortcuts) 函數, 設定方式較低階的 $.ajax() 簡單. 本篇測試其實是上一篇 jQuery 工具程式測試的延續, 因為篇幅太長切割為兩部分, 參考 :

jQuery 的工具函數測試

在測試這些 Ajax 捷徑函數之前, 先來測試 Ajax 的輔助函數與方法.


一. Ajax 輔助函數與方法 :

為了配合 Ajax 操作方便傳遞表單參數, jQuery 提供輔助函數如下表 :


 Ajax 輔助函數與方法 說明
 $.param(obj/array [,traditional]) 將物件或陣列序列化為查詢字串, traditonal 預設 false
 serialize() 將表單元件陣列元素之鍵值序列化為查詢字串
 serializeArray() 將表單元件陣列元素之鍵值轉成陣列


其中 $.param() 為工具函數, 是 jQuery 名稱空間內的頂層函數, 可直接用 $. 直接呼叫, 而 serialize() 與 serializeArray() 則是表單 form 物件或表單控制項物件陣列的方法, 必須在這些物件上才可呼叫. 在 Ajax 操作中最常用的是 serialize() 方法, 用來從表單產生 HTTP 請求所需之查詢字串, 它事實上是用 $.param() 為基礎打造的.


1. $.param() 函數 :

此工具函數會將傳入之物件或陣列轉成查詢字串, 其介面如下 :

$.param(object/array [, traditional])

第一個參數為要轉換之 Javascript/jQuery 物件或陣列, 第二個參數為備選之布林值, 用來設定是否要進行傳統之淺層序列化, 預設為 false. 傳回值為 "k1=v1&k3=v2 ..." 的格式化查詢字串, 例如 :


範例 1 : $.param() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var obj1={user:"tony",pwd:"123"};
        document.write('obj1={user:"tony",pwd:"123"}<br>');
        var qstr=$.param(obj1);
        document.write(qstr + '<br>');
        var obj2={a:1,b:{b1:2,b2:3},c:[4,5,6]};
        document.write('obj2={a:1,b:{b1:2,b2:3},c:[4,5,6]}<br>');
        var qstr=$.param(obj2);
        document.write(qstr + '<br>');
        });
    </script>
  </body>
</html>

此例用兩個物件 obj1 與 obj2 來測試 $.param(), 其中 obj1 是簡單的鍵值對物鍵, 而 obj2 則是具有兩層結構且有一個屬性值為陣列, 結果如下 :

obj1={user:"tony",pwd:"123"}
user=tony&pwd=123
obj2={a:1,b:{b1:2,b2:3},c:[4,5,6]}
a=1&b%5Bb1%5D=2&b%5Bb2%5D=3&c%5B%5D=4&c%5B%5D=5&c%5B%5D=6

可見簡單物件 obj1 經過 $.param() 轉換後就是單純的 k=v&k=v 格式的查詢字串, 而多層或含有陣列值的 obj2 則在轉出的查詢字串中含有 %5B (表示字元 '[') 與 %5D (表示字元 ']') 這些經 URL 編碼後的查詢字串, 這是用來表示物件結構的編碼字元, 所以 obj2 的輸出可以翻譯為 :

a=1&b[b1]=2&b[b2]=3&c[]=4&c[]=5&c[]=6

亦即, 深層物件會以 [屬性] 標示其鍵, 而陣列值則用空的 [] 表示其鍵. 不過實務上很少會用到深層物件結構會以陣列為值, $.param() 通常都用來從簡單的表單或其控制項陣列來轉換成查詢字串, 例如 :


範例 2 : $.param() 測試 (控制項陣列) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <form>
     <label for="user">帳號 : </label>
     <input type="text" id="user" name="user"><br>
     <label for="pwd">密碼 : </label>
     <input type="text" id="pwd" name="pwd">
     <button id="login">登入</button>
    </form>
    <div id="result"></div>
    <script>
      $(function(){
        $("#login").click(function(){
          var qstr=$.param($("input"));   //傳入 input 控制項物件陣列
          $("#result").html(qstr);
          return false;
          });
        });
    </script>
  </body>
</html>

此例以選擇器 $("input") 選取全部 input 控制項物件陣列, 傳入 $.param() 後, 這些元件的 name 與 value 會被組成查詢字串傳回來. 結果如下 :




注意, 控制項必須有 name 屬性, $.param() 以 name 作為查詢字串的 key, 如果只有 id 卻沒有 name, 則查詢字串將沒有 key (即變數名稱). 另外, 此利只是要測試 $.param() 功能並在網頁中顯示轉換結果, 並沒有要真的提交表單, 因此 click 事件結尾處要用 return false 阻止預設之提交動作與事件提升, 否則網頁會因提交重載而無法看到結果.

如果控制項含有 input, select, 與 textarea 等控制項, 則需要用複合選擇器來選取它們, 例如 :


範例 3 : $.param() 測試 (多種控制項) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <form>
      年收入 :
      <input type="radio" name="income">50 萬以下
      <input type="radio" name="income" checked>50~100 萬
      <input type="radio" name="income">100以上<br>
      投資經驗 :
      <input type="checkbox" name="experience1" checked>基金
      <input type="checkbox" name="experience1" checked>股票
      <input type="checkbox" name="experience1">選擇權
      <input type="checkbox" name="experience1">期貨<br>
      投資屬性 :
      <select name="risk">
        <option value="positive" selected>積極型</option>
        <option value="robust">穩健型</option>
        <option value="conservative">保守型</option>
      </select><br>
      備註 :
      <textarea name="remark" rows="5" cols="25">預設值</textarea><br>   
      <button id="ok">確定</button>
    </form>
    <div id="result"></div>
    <script>
      $(function(){
        $("#ok").click(function(){
          var qstr=$.param($("input,select,textarea"));
          $("#result").html(qstr);
          return false;
          });
        });
    </script>
  </body>
</html>

此例包含 input 的 radio, checkbox, select, 以及 textarea 等控制項, 故選擇器必須包含 input, select, 與 textarea, 結果如下 :



income=on&income=on&income=on&experience1=on&experience1=on&experience1=on&experience1=on&risk=positive&remark=test

結果每一個 radio 與 checkbox 選項都傳出 on, 這樣根本無法判別, 於是就有了下面以表單 form 物件的 serialize() 方法了.


2. serialize() 方法 :

上面的 $.param() 函數需以選擇器收集要轉換為查詢字串的控制項元件, 實務上提交表單是以表單為基礎, 因此 jQuery 在表單物件上用 $.param() 為基礎實作了 serialize() 方法, 可以將表單內之有效的控制項 (有 name 且不是 disabled 者) 全部轉成查詢字串, 其介面如下 :

serialize()

此方法無傳入參數, 傳回值為"k1=v1&k3=v2 ..." 的格式化查詢字串, 例如 :


範例 3 : .serialize() 方法測試 (表單) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <form id="login_form">
     <label for="user">帳號 : </label>
     <input type="text" id="user" name="user"><br>
     <label for="pwd">密碼 : </label>
     <input type="text" id="pwd" name="pwd">
     <button id="login">登入</button>
    </form>
    <div id="result"></div>
    <script>
      $(function(){
        $("#login").click(function(){
          var qstr=$("#login_form").serialize();
          $("#result").html(qstr);
          return false;
          });
        });
    </script>
  </body>
</html>

此例與上面使用 $.param() 函數之結果相同, 但做法改為用選擇器選取整個表單物件, 再呼叫其 serialize() 方法, 傳回格式化查詢字串, 結果如下 :




用這方法的好處是不需要用不同選擇器選取 input, select, 與 textarea 等不同控制項, 再傳給 $.param() 處理, 只要針對表單元件即可. 但同樣要注意的是, 表單內的每一個控制項都必須有 name 屬性.


3. serializeArray() 方法 :

此函數與 serialize() 方法一樣是表單物件之方法, 用來將表單內控制項要傳遞的變數轉成物件陣列, 其介面如下 :

serializeArray()

此函數無參數, 傳回值為物件陣列, 例如 :


範例 4 : .serializeArray() 方法測試 (表單) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <form id="login_form">
     <label for="user">帳號 : </label>
     <input type="text" id="user" name="user"><br>
     <label for="pwd">密碼 : </label>
     <input type="text" id="pwd" name="pwd">
     <button id="login">登入</button>
    </form>
    <div id="result"></div>
    <script>
      $(function(){
        $("#login").click(function(){
          var arr=[];    //儲存輸出訊息用
          var SA=$("#login_form").serializeArray();   //轉成物件陣列
          $.each(SA, function(idx, obj){       //迭代物件陣列
            arr.push("[" + idx + "]=" + obj);
            $.each(obj, function(k, v){            //迭代物件屬性
              arr.push(" " + k + ":" + v);
              });         
            });
          var qstr=$.param(SA);    //將物件陣列序列化
          arr.push(qstr);
          $("#result").html(arr.join("<br>"));
          return false;
          });
        });
    </script>
  </body>
</html>

此例取得表單物件後呼叫 serializeArray() 傳回控制項 name:value 組成之物件陣列, 故第一層迴圈迭代此陣列, 其元素就是控制項的鍵值物件, 因為有兩個控制項, 所以為陣列有兩個元素. 第二層迴圈迭代每一個元素 (即鍵值物件) 之屬性. 只要將 serializeArray() 傳回之物件陣列傳給 $.param() 函數就可以得到格式化的查詢字串了, 結果如下:




可見第一個物件是 user 控制項, 第二個物件是 pwd 控制項.


二. Ajax 捷徑函數 : 

jQuery 的 Ajax 捷徑函數如下表, 它們都會傳回一個 jqXHR 物件 :


 jQuery Ajax 捷徑工具函數 說明
 $.get(url [,data] [,success] [,dataType]) 指定 url 向伺服器發出 GET 請求
 $.post(url [,data] [,success] [,dataType]) 指定 url 向伺服器發出 POST 請求
 $.getJSON(url [,data] [,callback]) 指定 url 向伺服器發出 POST 請求 JSON 資料
 $.getScript(url [,callback]) 指定 url 向伺服器發出 POST 請求 Script 程式


其中 data 為要傳遞給後端伺服器之參數資料, 可以是 Javascript 物件或查詢字串, data 若為物件, 則其屬性值會以 URI 編碼成查詢參數. dataType 指定以何種格式解析 HTTP 回應本體 (body) 中的資料, 可用 html, txt, xml, json, jsonp, script 等格式. 參數 success 為收到 HTTP 回應狀態為成功時財呼叫的回呼函數 (失敗就不呼叫), 此回呼函數有三個參數 :

function(data, textStatus, jqXHR) {}

其中參數 data 為伺服器的回應資料 (html, txt, xml, json, script 等物件), 參數 textStatus 為回應狀態字串 (success, error, notmodified, timeout 等), 參數 jqXHR 為一個物件. 這是一個 XMLHttpRequest 物件的子集.

這些快捷函數都是由低階的 $.ajax() 再包裝而成, 關於 $.ajax() 參考 :

測試 jQuery 的 Ajax 函數 $.ajax()


1. $.get() 函數 :

此函數會以 GET 方法向伺服器發出非同步請求, 其介面如下 :

$.get(url [,data] [,callback] [,dataType])

此函數相當於下列 $.ajax() 的封裝 :

$.ajax({
  type: "GET",
  url: url,
  data: data,
  success: success,
  dataType: dataType
  });

由於 type 已經設為 GET, 因此 HTTP 要求為 GET 方法, 所以不論參數放在  url 中或以參數物件放在 data 屬性中, Ajax 引擎都會把參數轉成查詢字串放在 URL 後面, 因此後端 PHP 程式都要用 $_GET[] 函數捕捉, 例如 :


範例 5 : $.get() 帶 URL 查詢字串載入 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="get" value="get">
  <script> 
    $(function(){
      $("#get").click(function() {
        $.get({
          url: "test.php",
          dataType: "html",
          data: "user=tony&pwd=123",
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

此例將全部參數以字串形式放在 data 屬性中, 結果如下 :





若將參數分散在 URL 查詢字串與 data 屬性的參數物件中, 結果也跟上面範例 5 完全一樣, 都要用 $_GET[] 函數捕捉, 例如 :


範例 6 : $.get() 帶 URL 查詢字串與參數物件載入 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="get" value="get">
  <script> 
    $(function(){
      $("#get").click(function() {
        $.get({
          url: "test.php?user=tony",
          dataType: "html",
          data: {pwd: 123},
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

即使將參數完全以 data 屬性參數物件形式, 結果參數也是轉成查詢字串 :


範例 7 : $.get() 以 data 參數物件請求 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="get" value="get">
  <script> 
    $(function(){
      $("#get").click(function() {
        $.get({
          url: "test.php",
          dataType: "html",
          data: {user: "tony", pwd: 123},
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

綜合以上測試, $.get() 函數不管參數以哪種形式表達, 都會被轉成 URL 查詢字串傳送, 所以後端都要用 $_GET[] 捕捉.

下面範例使用 $.get() 向後端請求 test_xml.php, 此程式會回應一個 XML 格式資料 :

<?php
//test.xml.php
header("Content-Type: text/xml");
$user=$_REQUEST["user"];           
$pwd=$_REQUEST["pwd"];
$response="<?xml version='1.0' ?>".
          "<result>".
          "<user>".$user."</user>".
          "<pwd>".$pwd."</pwd>".
          "</result>";
echo $response;
?>

此程式會將捕捉到的參數以 XML 格式包裝後回應給客戶端.


範例 8 : 用 $.get() 請求 XML 資料 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form id="login_form">
   <label for="user">帳號 : </label>
   <input type="text" id="user" name="user"><br>
   <label for="pwd">密碼 : </label>
   <input type="text" id="pwd" name="pwd">
   <button id="login">登入</button>
  </form>
  <div id="result"></div>
  <script>
    $(function(){
      $("#login").click(function(){
        $.get({
          url: "test_xml.php",
          data: $("#login_form").serialize(),
          success: function(data) {
            var user=$(data).find("user").text();
            var pwd=$(data).find("pwd").text();
            var result="帳號=" + user + " 密碼=" + pwd;
            $("#result").html(result);
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

此例使用表單物件的 serialize() 方法將控制項的 name:value 序列化為查詢字串, $.get() 函數會將其附在 URL 字串後面送出 GET 請求, 收到 XML 回應資料 data 後將其轉成 jQuery 物件, 方便使用 find() 方法找出 XML 節點元素, 結果如下 :




比 XML 還要輕巧的 JSON 現在已成為資料交換的新寵兒, 為了透過 $.get() 取得後端的 JSON 資料, 需準備一個後端程式 tes_json.php 程式如下 :

<?php
//test_json.php
header("Content-Type: application/json");
$user=$_REQUEST["user"];           
$pwd=$_REQUEST["pwd"];
$response=array(
  'user' => 'tony',
  'pwd' => '123'
  );
echo json_encode($response);
?>

此程式利用 json_encode() 將陣列轉換成如下 JSON 資料 :

{"user":"tony","pwd":"123"}


範例 9 : 用 $.get() 請求 JSON 資料 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form id="login_form">
   <label for="user">帳號 : </label>
   <input type="text" id="user" name="user"><br>
   <label for="pwd">密碼 : </label>
   <input type="text" id="pwd" name="pwd">
   <button id="login">登入</button>
  </form>
  <div id="result"></div>
  <script>
    $(function(){
      $("#login").click(function(){
        $.get({
          url: "test_json.php",
          data: $("#login_form").serialize(),
          success: function(data) {
            var user=data.user;
            var pwd=data.pwd;
            var result="帳號=" + user + " 密碼=" + pwd;
            $("#result").html(result);
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

此例收到後端回應 {"user":"tony","pwd":"123"} 後, 會傳入 success 屬性的回呼函數參數 data, 這樣就可以直接用物件屬性 data.user 與 data.pwd 取得回應資料之值, 不需要從 data 回應中撈資料, 這是 JSON 比 XML 方便的地方. 結果如下 :




綜合以上 $.get() 的測試可知此函數會以 GET 方法發出 HTTP 請求, 不論參數是帶在 url 查詢字串還是 data 參數物件上, 它都會將參數全部轉成查詢字串附在網址後面送出, 摘要如下表 :


 url 屬性 data 屬性 HTTP 請求 後端 PHP 讀取參數
 test.php?a=1&b=2 無 GET $_GET["a"] 與 $_GET["b"]
 test.php?a=1 {b: 2} GET $_GET["a"] 與 $_GET["b"]
 test.php {a:1, b: 2} GET $_GET["a"] 與 $_GET["b"]
 test.php a=1&b=2 GET $_GET["a"] 與 $_GET["b"]


GET 是一種等冪操作 (idempotent), 意思是同樣的 GET 請求重複操作會得到一樣的結果, 通常用來從伺服器取得資料; 而 POST 則是非等冪操作 (non-idempotent), 傳送給伺服器的參數通常用來改變後端伺服器狀態, 例如資料庫內容異動等, 故資料庫的 CRUD 操作應該用 POST.


2. $.post() 函數 :

此函數會以 POST 方法向伺服器發出非同步請求, 其介面如下 :

$.post(url [,data] [,callback] [,dataType])

此函數相當於下列 $.ajax() 的封裝 :

$.ajax({
  type: "POST",
  url: url,
  data: data,
  success: success,
  dataType: dataType
  });

由於 type 已經設為 POST, 因此 HTTP 要求為 POST 方法, 所以不論參數放在  url 中或以參數物件放在 data 屬性中, Ajax 引擎都會把參數放在 HTTP 本體 (body) 內傳送, 因此後端 PHP 程式都要用 $_POST[] 函數捕捉, 例如 :


範例 10 : $.post() 帶 URL 查詢字串載入 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="post" value="post">
  <script> 
    $(function(){
      $("#post").click(function() {
        $.post({
          url: "test.php",
          dataType: "html",
          data: "user=tony&pwd=123",
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

此例用 $.post() 載入一個 htm 網頁, 參數以查詢字串方式放在 data 屬性中傳送, 結果如下 :





可見雖然 data 屬性值是查詢字串, 還是會被放在 HTTP 本體 (body) 中傳送, 因此後端要用 $_POST[] 捕捉. 如果參數一部分放 URL 字串, 另一部分放在 data 字串, 則 $.post() 會怎麼傳送變數呢? 參考


範例 11 : $.post() 帶查詢字串與參數物件載入 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="post" value="post">
  <script> 
    $(function(){
      $("#post").click(function() {
        $.post({
          url: "test.php?user=tony",
          dataType: "html",
          data: "pwd=123",
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

此例將兩個參數一個放 URL 查詢字串, 一個放在 data 查詢字串, 結果如下 :





可見使用 $.post() 發出 Ajax 請求時, 雖然 HTTP 請求方法是 POST, 但放在 url 屬性中的參數會以查詢字串方式附在 URL 中送出, 而放在 data 屬性中的字串參數則放在 HTTP 本體中傳送.

下面則是全部參數以物件形式放在 data 屬性中的範例 :


範例 12 : $.post() 以 data 參數物件載入 PHP 網頁 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <div id="result">This is a div container</div>
  <input type="button" id="post" value="post">
  <script> 
    $(function(){
      $("#post").click(function() {
        $.post({
          url: "test.php",
          dataType: "html",
          data: {user: "tony", pwd: 123},
          success: function(data) {
            $("#result").html(data);
            }     
          });
        });
      });
  </script>
  </body>
</html>

結果如下 :





可見若 data 屬性值為物件, 則 $.post() 會將這些參數都放在 HTTP 本體中傳送.

綜合以上 $.post() 的測試可知, 此函數會以 POST 方法發出 HTTP 請求, 帶在 url 屬性中的參數會以查詢字串附在網址後面送出, 而帶在 data 屬性中的參數, 不論是字串或物件形式, 都會放在 HTTP 本體中送出, 摘要如下表 :


 url 屬性 data 屬性 HTTP 請求 後端 PHP 讀取參數
 test.php?a=1&b=2 無 POST $_GET["a"] 與 $_GET["b"]
 test.php?a=1 {b: 2} POST $_GET["a"] 與 $_POST["b"]
 test.php {a:1, b: 2} POST $_POST["a"] 與 $_POST["b"]
 test.php a=1&b=2 POST $_POST["a"] 與 $_POST["b"]


下面為以 $.post() 取得 XML 回應資料之範例, 後端 PHP 程式仍然是上面 $.get() 所用的 test_xml.php.


範例 13 : 用 $.post() 請求 XML 資料 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form id="login_form">
   <label for="user">帳號 : </label>
   <input type="text" id="user" name="user"><br>
   <label for="pwd">密碼 : </label>
   <input type="text" id="pwd" name="pwd">
   <button id="login">登入</button>
  </form>
  <div id="result"></div>
  <script>
    $(function(){
      $("#login").click(function(){
        $.post({
          url: "test_xml.php",
          data: $("#login_form").serialize(),
          success: function(data) {
            var user=$(data).find("user").text();
            var pwd=$(data).find("pwd").text();
            var result="帳號=" + user + " 密碼=" + pwd;
            $("#result").html(result);
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

此例先將回應之 XML 字串用 $() 工廠函數轉成 jQuery 物件, 以便用 find() 函數找尋 XML 節點元素. 此程式與上面範例 8 之差別只是將 $.get() 改為 $.post() 而已, 結果一樣得到下列 XML 回應 :

<?xml version='1.0' ?><result><user>tony</user><pwd>123</pwd></result>

下面為以 $.post() 取得 JSON 回應資料之範例, 後端 PHP 程式仍然是上面 $.get() 所用的 test_json.php.


範例 14 : 用 $.post() 請求 JSON 資料 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form id="login_form">
   <label for="user">帳號 : </label>
   <input type="text" id="user" name="user"><br>
   <label for="pwd">密碼 : </label>
   <input type="text" id="pwd" name="pwd">
   <button id="login">登入</button>
  </form>
  <div id="result"></div>
  <script>
    $(function(){
      $("#login").click(function(){
        $.post({
          url: "test_json.php",
          data: $("#login_form").serialize(),
          success: function(data) {
            var user=data.user;
            var pwd=data.pwd;
            var result="帳號=" + user + " 密碼=" + pwd;
            $("#result").html(result);
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

此程式與上面範例 9 差別只是將 $.get() 換成 $.post() 而已, 結果完全一樣, 都會得到如下 JSON 回應 :

{"user":"tony","pwd":"123"}

除了可用 $.get() 或 $.post() 取得後端 JSON 回應資料, jQuery 還提供了 JSON 專用的工具函數 $.getJSOM().


3. $.getJSON() 函數 :

此函數會以 POST 方法向伺服器發出非同步請求, 其介面如下 :

$.getJSON(url [,data] [,callback] [,dataType])

此函數相當於下列 $.ajax() 的封裝 :

$.ajax({
  type: "POST",
  url: url,
  data: data,
  success: success,
  dataType: "json"
  });

由於 type 已經設為 POST, 因此 HTTP 要求為 POST 方法, 所以不論參數放在  url 中或以參數物件放在 data 屬性中, Ajax 引擎都會把參數放在 HTTP 本體 (body) 內傳送, 因此後端 PHP 程式都要用 $_POST[] 函數捕捉, 例如 :


範例 15 : 用 $.getJSON() 請求 JSON 資料 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form id="login_form">
   <label for="user">帳號 : </label>
   <input type="text" id="user" name="user"><br>
   <label for="pwd">密碼 : </label>
   <input type="text" id="pwd" name="pwd">
   <button id="login">登入</button>
  </form>
  <div id="result"></div>
  <script>
    $(function(){
      $("#login").click(function(){
        $.getJSON({
          url: "test_json.php",
          data: $("#login_form").serialize(),
          success: function(data) {
            var user=data.user;
            var pwd=data.pwd;
            var result="帳號=" + user + " 密碼=" + pwd;
            $("#result").html(result);
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

結果如下 :




可見雖然名稱為 $.getJSON(), 但發出的 HTTP 請求卻是 POST.


4. $.getScript() 函數 :

此函數會以 POST 方法向伺服器發出非同步請求, 其介面如下 :

$.getScript(url [,data] [,callback])

此函數相當於下列 $.ajax() 的封裝 :

$.ajax({
  type: "script",
  url: url,
  success: success,
  });

為了這個測試, 準備了一個 Javascript 程式 test_script.js 如下 :

alert("ok");

利用 $.getScript() 載入 test_script.js 後就會立即執行.


範例 16 : $.getScript() 載入 Javascript [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
  <form>
   <button id="load">載入 Script</button>
   <div id="result"></div>
  </form>
  <script>
    $(function(){
      $("#load").click(function(){
        $.getScript({
          url: "test_script.js",
          dataType: "script",
          success: function() {
            $("#result").html("Ajax 請求成功!<br>");
            }
          });
        return false;
        });
      });
  </script>
  </body>
</html>

此例在載入成功後會先執行 Javascript 然後再執行回呼函數, 結果如下 :




參考 :

jquery getScript動態載入JS方法改進詳解

除了用 jQuery 工具函數進行 Ajax 操作外, jQuery 還有一個 DOM 元素物件的 load() 方法可進行 Ajax 存取, 用來直接將 Ajax 回應資料插入 DOM 元素的內容中, 參考 :

測試 jQuery 的 Ajax 方法 load()

OK! 終於在 2019 年的年尾將 jQuery 的 Ajax 全部測試完畢了, 完工!

沒有留言 :