2020年8月24日 星期一

jQuery 常用技法整理

最近因為改寫公司作業自動化工具的需要重新複習 jQuery, 同時把向市圖借的 jQuery 書籍摘要整理一下趕快還掉, 以免佔用我的書架. 參考書目如下 :
  1. 鋒利的 jQuery (佳魁)
  2. 打造 jQuery 網頁風暴 (佳魁)
  3. jQuery 應用程式設計極速上手 (上奇)
  4. jQuery 高手精技 (旗標)
  5. jQuery 實戰手冊第三版 (碁峰)
  6. jQuery 最強圖解實戰講座 (旗標)
  7. JavaScript 函數活用範例速查辭典 (博碩)
  8. Learning jQuery3 5th Edition (Packt)
  9. JavaScript & jQuery-The Missing Manual (O'Reilly)
其中第 4 與第 6 本旗標的書均翻譯自日文著作, 裡面有許多不依賴 UI 的實作練習, 在寫特色網站時非常值得參考 (尤其是高手精技這本特色是於練習中附帶 API 解說), 但對於只是要呈現內容的網站 (例如顯示或查詢工程感測數據) 而言就不需要, 直接用 jQuery UI 更簡單方便. 第 8 本歐萊里的 Missing Manual 裡面有非常多的實用簡短範例, 是可快速翻查的工作手冊.

jQuery 的 API 參考 :

https://api.jquery.com/

jQuery 的語法很簡單, 就是先用工廠函數 $() 以選擇器取得元素的 jQuery 物件 (集合), 再呼叫其物件方法 :

$(選擇器).方法(參數1, 參數2, ....)   

選擇器語法是在 CSS 選擇器基礎上再添加一些 jQuery 自己的選擇器, 因此用法基本上與 CSS 選擇器相同, 其次, 有些方法的參數可能是個函式. 

以下是 jQuery 的常用技法, 大多是 jQuery 物件的方法或函數. jQuery 的方法與函數在使用上與 Javascript 最大的不同有如下兩點 :

1. 函式串接 (chaining functions 或 method chains) :

jQuery 物件的方法或 jQuery 頂層函式都可以用點運算符連續串接, 例如 :

$("#img1").width(200).height(300);

2. 自動迴圈 (automatic loops) :  

如果使用 Javascript 操作 DOM 來處理頁面元素的屬性與行為, 例如隱藏頁面中的所有圖片 :

$("img").hide();

選擇器 $("img") 選取了頁面中全部圖片, 如果用 Javascript 去設定這些圖片的樣式來隱藏勢必需要使用迴圈, 呼叫 hide() 卻只需要一個指令, 事實上 jQuery 是在背後自動用迴圈處理掉了.


一. 常用選擇器 : 

jQuery 採用 CSS 的選擇器語法來取得網頁元素, 以下為最常用的基本選擇器用法 :


1. id 選擇器 (# id selector) : 

使用 # 與元素的 id 屬性 (具有唯一識別性) 來取得網頁元素, 語法為 $("#id"),  例如下列 id=mydiv 的 div 元素 :

<div id="mydiv"></div>

則 $("#mydiv") 將傳回此 div 元素的 jQuery 物件 (應該是唯一) :

var mydiv=$("#mydiv");


2. 類別選擇器 (. class selector) : 

類別選擇器使用 "." 與元素的樣式類別來取得網頁元素, 語法為 $(".樣式類別名稱"), 由於網頁中可能有多個元素套用相同樣式類別, 因此它會傳回一個 jQuery 物件集合 (collection), 例如 :

<ul>
  <li class="myclass">A</li>
  <li class="myclass">B</li>
  <li class="myclass">C</li>
</ul>

則 $(.myclass) 將傳回一個 jQuery 物件集合, 類似陣列, 可用 length 屬性取得其長度, 也可用 each() 工具函數拜訪集合之元素 :

var myclass=$(".myclass");
console.log(myclass.length);    //輸出 3
myclass.each(function(idx){       
  console.log(idx + " " + $(this).text());   //分別輸出 0 A, 1 B, 2 C
  });

此處回呼函數內的 this 為配選取之 DOM 元素, 不是被選取的 jQuery 物件, 必須傳入 $() 才是.


3. 元素選擇器 (element selector)  : 

元素選擇器以元素的標籤篩選網頁中的元素, 語法為 $("標籤"), 例如下列選項清單中的 li 元素 :

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

由於指定的標籤在網頁中可能有多個, 因此也是傳回一個 jQuery 物件集合 :

var myli=$("li");
console.log(myli.length);    //輸出 3
myli.each(function(idx){       
  console.log(idx + " " + $(this).text());   //分別輸出 0 A, 1 B, 2 C
  });


4. 後代選擇器 (descendant selectors) : 

此選擇器可篩選某元素的所有後代元素, 可精確選取所要的元素, 語法為 $("父元素選擇器 後代元素選擇器"), 即中間空一格, 例如下面的 li 是 div 的後代元素 :

<div id="mydiv">
  <ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
  </ul>
</div>

如果只用元素選擇器 $("li") 將選取頁面上的全部 li 元素, 而使用 $(#myul li) 才能精確選取這三個 li 元素.

var myli=$("#mydiv li");
console.log(myli.length);    //輸出 3
myli.each(function(idx){       
  console.log(idx + " " + $(this).text());   //分別輸出 0 A, 1 B, 2 C
  });


5. 子元素選擇器 (child selector) : 

此選擇器用來選取子元素 (即直接後代, 不含孫元素), 語法是 $("父元素 > 子元素"), 例如下面的 li 是 ul 元素的子元素 :

<ul id="myul">
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

先用 id 選擇器選取父元素 ul, 再用子元素選擇器選取子元素 :

var myli=$("#myul > li");
console.log(myli.length);    //輸出 3
myli.each(function(idx){       
  console.log(idx + " " + $(this).text());   //分別輸出 0 A, 1 B, 2 C
  });


6. 次元素選擇器 (adjacent selector) : 

此選擇器選取緊鄰的下一個元素, 語法為 $("前元素 + 次元素"), 傳回值為一個 jQuery 物件, 不是物件集合, 例如下列網頁 :

<h3>A</h1>
<div>B</div>
<div>C</div>

則 $("h3 + div") 會選取 h3 元素後面跟著的第一個 div 元素 :

var next=$("h3 + div");
console.log(next.length);    //輸出 1
console.log(next.text());     //輸出 B


7. 所有次元素選擇器 (following-all-siblings selector) : 

此選擇器選取所有後面的兄弟元素 (siblings), 語法為 $("前元素 ~ 次元素"), 傳回值為 jQuery 物件集合, 例如下列網頁 :

<h3>A</h1>
<div>B</div>
<div>C</div>

則 $("h3 ~ div") 會選取 h3 元素後面跟著所有同層元素 :

var nextALL=$("h3 ~ div");
console.log(nextALL.length);    //輸出 2
nextALL.each(function(idx){     
  console.log(idx + " " + $(this).text());   //分別輸出 0 B, 1 C
  });


8. 屬性選擇器 (attribute selector) :

此選擇器用來選取屬性值符合特定條件之元素 :


 屬性選擇器 說明
 [attr] 選取全部具有 attr 屬性的元素, 例如 [class] 選取所有含 class 屬性之元素
 [attr=foo] 選取 attr 屬性全等於 foo 之全部元素, 例如 [name=fruits]
 [attr!=foo] 選取 attr 屬性不等於 foo 之全部元素, 例如 [name!=fruits]
 [attr^=foo] 選取 attr 屬性以 foo 開頭之全部元素, 例如 [href^=https]
 [attr$=foo] 選取 attr 屬性以 foo 結束之全部元素, 例如 [href$=tw]
 [attr*=foo] 選取 attr 屬性包含 foo 之全部元素 (含子字串), 例如 [href*=org]
 [attr~=foo] 選取 attr 屬性 (以空格隔開) 包含 foo 之全部元素 (不含子字串), 例如 [class~=foo]
 [attr|=foo] 選取 attr 屬性全等於 foo 或以 foo 開頭之全部元素, 例如 [class|=foo]


其中 [attr*=foo] 與 [attr~=foo] 的差異在於 [attr*=foo] 會包含子字串; 而 [attr~=foo] 則不包含, 在屬性值有多個以空格隔開情形就能看出差異, 例如 class="foo foo1" 與 class="foofoo1" 若用 [attr*=foo] 兩者都會被選到, 但若用 [attr~=foo] 則只有前者會被選到, 因為後者是在子字串中找到 foo, 而 [attr~=foo] 不含子字串, 它是要在空格隔開中全等才符合.


9. 表單選擇器 (form selector) :

此選擇器用於選取表單元素 (form) 內部的 input, select, button, 以及 textarea 等元素, 均以冒號開頭, 為了便於閱讀, 除了 :input 選擇器外, 其他選擇器最好加上標籤名稱, 例如用 input:text, input:radio 或 select:selected 等等 :


 表單選擇器 說明
 :input 選取所有表單元素, 包含 input, select, textarea, 與 button
 :text 選取所有文字欄位元素, 即 <input type="text">
 :password 選取所有密碼欄位元素, 即 <input type="password">
 :radio 選取所有單選圓鈕元素, 即 <input type="radio">
 :checkbox 選取所有核取方塊元素, 即 <input type="checkbox">
 :submit 選取所有提交按鈕元素, 即 <input type="text"> 與 <button type="button">
 :image 選取所有提交圖片按鈕元素, 即 <input type="image">
 :reset 選取所有重設按鈕元素, 即 <input type="reset"> 與 <button type="reset">
 :button 選取所有按鈕元素, 即 <input type="button"> 與 <button type="button">
 :file 選取所有檔案上傳欄位元素, 即 <input type="file">
 :enabled 選取所有啟用 (可與使用者互動) 之表單元素, 即無 disabled 屬性之表單元素
 :disabled 選取所有停用 (無法與使用者互動) 之表單元素, 即有 disabled 屬性之表單元素
 :checked 選取所有被核取之表單元素, 包含被核取之 checkbox 與 radio 元素
 :selected 選取所有被選擇之 select 元素中的 option 元素



二. 常用 jQuery 物件方法 : 


1. 操作網頁元素之隱藏與顯示 :

呼叫 hide() 方法可隱藏網頁元素, 而 show() 則可使其顯示, 例如 :

$("#element").hide(); 
$("#element").show();

呼叫 hide() 時此函數會先將該元素的 display 樣式值 (inline 或 block 等) 記下來, 然後再將該元素的 display 樣式設為 none, 這與呼叫 $("#element").css("display", "none") 的效果一樣;  而呼叫 show() 時此函數會將原先記下來的 display 樣式值恢復 (例如 inline 或 block).


2. 操作網頁元素的內容 : 

所謂網頁元素的內容是指有開始與結束標籤的元素而言, 其內容即夾在兩者之間的部分 (會顯示在瀏覽器上), 也就是 DOM 物件中 innerHTML 屬性之值, 例如下面的 p 元素 :

<p id="para">Hello World</p>

呼叫 html() 即可取得 p 元素的 innerHTML 屬性值 "Hello World" :

$("#papa").html();   //取得網頁元素的內容

如果傳參數 (字串) 進去, 那就是設定 (修改) p 元素的內容 :

$("#papa").html("<b>How are you?</b>");   ////修改網頁元素的內容

另外還有一個 text() 函數可用來存取元素的純文字內容 (去除 HTML 標籤的部分, 包含跳行等字元), 也就是 DOM 物件中的 innerText 屬性之值 :

$("#papa").text();    //取得網頁元素的 innerText 內容
$("#papa").text("How are you?");    //設定網頁元素的 innerText 內容

如果要將某個元素的 innerHTML 內容清空, 可用 empty() 方法達成, 例如上面 id=para 的 p 元素 :

$("#para").empty(); 

這樣會使該 p 元素內容變空白 (但 p 標籤仍在) :

<p id="para"></p>

如果要將某個元素以新的內容或新的標籤取代, 可呼叫 replaceWith(), 例如要將上面的 p 元素內容改為 "How are you" 可以這麼做 :

$("#para").replaceWith("<p id="para">How are you</p>");

注意, 傳入的參數會完全取代該元素 (包含標籤), 因此若只傳入內容 $("#para").replaceWith("How are you"), 則連 p 元素的開始與結束標籤都不見了, 只剩下 "How are you", 因此 replaceWith() 也可以用來更換元素, 例如將 p 元素換成 div 元素 :

$("#para").replaceWith("<div id="para">How are you</div>");


3. 操作網頁元素的屬性 : 

呼叫 attr() 方法可操作元素的屬性, 只傳入一個參數為 getter; 傳入兩個參數為 setter :

obj.attr("屬性名稱") : 傳回屬性值
obj.attr("屬性名稱", "屬性值") : 設定屬性值

例如網頁元素 p :

<p id="para" style="color: blue;">Hello World</p>

var style=$("#para").attr("style");    //傳回 "color: blue;"
$("#para").attr("style", "color: green;");    //設定前景色為 green

attr() 方法很廣用, 例如可用來操作樣式屬性 style 與類別 class.


4. 操作網頁元素的尺寸 :

呼叫 width() 與 height() 可存取網頁元素的尺寸, 語法如下 :

obj.width() : 傳回元素寬度  (數值 : 單位 px)
obj.width(寬度) : 設定元素寬度 (數值或帶 px 單位字串)
obj.height() : 傳回元素長度  (數值 : 單位 px)
obj.height(長度) : 設定元素長度 (數值或帶 px 單位字串)

注意, width() 與 height() 的傳回值是不附單位的數值 (預設單位是 px), 這與呼叫 css("width") 或 css("heigght") 不同, 後者是有帶單位的. 例如下面的按鈕 :

<button id="btn">OK</button>

用 css() 與 width() 取得的預設按鈕寬度不同 :

console.log($("#btn").css("width"));   //輸出 35.2557px  (帶單位且為外尺寸)
console.log($("#btn").width());           //輸出 19.25947 (不帶單位且為內尺寸)

但若經過設定, 取回的值就一樣了 :

<button id="btn1">OK</button><br>
<button id="btn2">OK</button>

$("#btn1").css("width","100px"); 
$("#btn2").width("100px");
console.log($("#btn1").css("width"));   //傳回 100px
console.log($("#btn2").width());   //傳回 100

但用 width() 設定的寬度會比較大一些.

若要從 css() 的帶單位傳回值取出數值, 可用 Javascript 的 parseInt() 函數 :

console.log(parseInt($("#btn1").css("width")));   //傳回 100


5. 操作網頁元素的樣式 :

呼叫 css() 方法可操作元素的樣式, 只傳入一個參數為 getter; 傳入兩個參數為 setter :

obj.css("樣式名稱") : 傳回樣式內容
obj.css("樣式名稱", "樣式內容") : 設定樣式內容

傳入雜湊物件 (鍵值對) 則可一次設定多個樣式 :

obj.css({"樣式名稱1":"樣式內容1", "樣式名稱2":"樣式內容2"} ...) : 設定多個樣式內容

例如網頁元素 p :

<p id="para" style="color: blue;">Hello World</p>

var style=$("#para").css("color");    //傳回 "blue"
$("#para").css("color", "green");    //設定前景色為 "green"
$("#para").css({"color":"green", "font-color":"#0000ff"});  //設定多個樣式

注意, css() 傳回的是 style 屬性中完整的樣式設定, 例如 :

<p id="foo" style="width:200px;color=blue">A</p>

$("#foo").css("width") 傳回值是帶單位的 "200px", 而 $("#foo").width() 傳回的是不帶單位的 "200".


6. 操作網頁元素的樣式類別 : 

呼叫 addClass() 添加樣式 (原有樣式仍在但可能被覆蓋); 呼叫 removeClass() 則移除指定樣式 :

obj.addClass("樣式類別名稱");    //添加樣式類別
ㄌobj.removeClass("樣式類別名稱");    //移除已存在之樣式類別

例如網頁元素 p :

<p id="para">Hello World</p>

可用 $("#para").addClass("p1") 添加下列樣式類別 :

.p1 {color: blue; font-style: italic}

呼叫 $("#para").removeClass("p1") 則可移除已有之樣式類別 p1.

如果要直接覆蓋已有之全部樣式類別可以呼叫 attr() :

obj.attr("class", "樣式類別名稱");    //設定物件之樣式類別 (完全覆蓋)

判斷物件是否含有指定樣式類別可呼叫 hasClass() 方法 :

obj.hasClass("樣式類別名稱");   //若含有指定之樣式類別傳回 true, 否則傳回 false

這可用來切換 (toggle) 是否要套用某個樣式類別 (如果沒有就套用, 已有就移除). 不過 toggle 的功能 jQuery 已經有一個現成的方法 toggleClass() 可用來切換類別是否套用 :

obj.toggleClass("樣式類別名稱");  //若元素無此類別樣式就套用, 若已套用就移除

也可以傳入第二個參數 switch (布林判斷式, 例如 a == 5) 來決定是否套用 :

obj.toggleClass("樣式類別名稱", switch);  //若 switch=true 就套用樣式類別, 否則就移除


7. 操作表單元素的內容 : 

呼叫 val() 方法可以存取文字類表單元件例如 input 文字欄位 (type=text), 密碼欄位 (type=password), 以及文字區域 textarea 等 :

obj.val();    //傳回物件之 value 屬性值
obj.val("請輸入 email");     //設定物件之 value 屬性值

但是對於選項類元件則需配合選擇器才能取得被選擇之選項值.

對於 radio 或 checkbox 元件, 要取得被選取的選項值 (radio) 或值陣列 (checkbox) 除了使用 $("[name=元素名稱]") 外還必須再加上屬性過濾選擇器 :checked 才行, 如果只用 $("[name=元素名稱]"), 則呼叫 val() 會固定傳回第一個選項之值 (不管有沒有選都一樣), 正確的用法如下 :

$("[name=元素名稱]:radio:checked").val();     //取得被選取之 radio 選項值 (單選)

對於可複選的核取方塊 checkbox, 即使選擇器使用 $("[name=元素名稱]:checkbox:checked"), 呼叫 val() 仍然只會傳回第一個選項值, 因為它的傳回值是一個陣列, 必須使用一個空陣列並透過 each 迴圈來逐一將被選取選項值放入空陣列中以取得被選取值陣列, 例如 :

var selected=[];
$("[name=元素名稱]:checkbox:checked").each(function(){
  selected.push($(this).val());
  })

對於單選的下拉式選單 select (無 multiple 屬性者), 直接呼叫 val() 即可取得被選取之選項值, 若都未選傳回 null; 對於可複選的下拉式選單 (有 multiple 屬性者), 取得被選取選項值的做法與 checkbox 類似, 以過濾選擇器 "[name=元素名稱]:selected" 取得物件後, 呼叫 each() 拜訪傳回值陣列, 並將其存入空陣列之中 :

var selected=[];
$("[name=元素名稱]:selected").each(function(){
  selected.push($(this).val());
  })


8. 事件綁定與處理 : 

jQuery 支援滑鼠, 鍵盤, 以及表單等事件, 在 v1.7 版後它棄用 bind() 與 live() 等方法, 改用 on() 的方法來綁定事件與其事件處理函式, 其 API 有如下兩種 :

obj.on(eventType [, selector] [, data], function(e) {})
obj.on(eventsHash [, selector] [, data])

第一參數是要綁定的事件類型字串或事件雜湊, 前者可以是單一的事件類型字串例如 "click", 也可以是以空格隔開的多個事件類型字串例如 "click mouseover keydown" (多個事件綁定一個事件處理函式). 第一參數也可以是以事件類型與其處理函式組成的鍵值對 (hash), 可用來一次綁定多個事件.

備選之第二參數 selector 是事件委託 (event delegation) 的選擇器字串, 用來過濾被選取元素中觸發事件之子節點, 亦即子節點觸發事件, 但是卻在父元素綁定事件處理器. 事件委託給父元素在 以 Ajax 載入子節點操作時很好用, 因為要觸發事件之子節點尚未存在, 只好將事件處理函式綁定給父元素.

備選之第三參數是要傳給事件物件 e 的參數 (鍵值對), 可在事件處理函式中以 e.data 第四參數為必要之事件處理函數. 如果不需要第二與第三參數也不需要傳入兩個 null, 直接略過即可 (jQuery 會自動處理).

jQuery 支援之事件類型如下 :


 滑鼠事件 說明
 click 點擊元素
 dbclick 雙擊元素
 mouseenter 滑鼠游標滑入元素
 mouseover 滑鼠游標滑入元素
 mouseleave 滑鼠游標移出元素
 mouserout 滑鼠游標移出元素
 mousemove 滑鼠游標在元素上移動
 mouseup 放開滑鼠左鍵
 mousedownn 按下滑鼠左鍵

 鍵盤事件 說明
 keydown 按下鍵盤按鍵
 keypress 持續按下鍵盤按鍵
 keyup 放開鍵盤按鍵

 表單事件 說明
 blur 焦點離開表單元素
 focus 焦點進入表單元素
 change 元素值變更 (text, textarea)
 select 文字被選取 (text, textarea)
 submit 提交表單
 focusin 焦點進入表單元素
 focusout 焦點離開表單元素

 其他事件 說明
 resize 視窗大小改變
 scroll 頁面或元素被捲動
 contextmenu 內容選單顯示之前


其中最常用的是按鈕的 click 事件, 例如下列按鈕 :

<button id="btn">按我</button>

呼叫 button 元素物件的 on() 方法為其綁定 click 事件 :

$("#btn").on("click", function(e){
  alert("你按了按鈕!");
  });

可以多個事件綁定一個事件處理函式, 各事件類型字串以空格隔開, 例如 :

$("#btn").on("click mouseover", function(e){
  alert("你按了按鈕!");
  });

傳入第二參數 data 可將資料以鍵值對 (物件) 傳遞給事件物件 e, 在回呼函數中可用 e.data.屬性名稱取值, 例如 :

$("#btn").on("click", {"name":"Tony"}, function(e){
  alert(e.data.name + " 按了按鈕!");     //顯示 "Tony 按了按鈕"
  })

對於這些事件, jQuery 物件也有捷徑方法可以直接綁定事件處理函式 (語法較簡短), 例如 :

$("#btn").click(function(e){
  alert("你按了按鈕!");
  })

捷徑方法也可以傳遞 data 參數 (備選第一參數) :

$("#btn").click({"name":"Tony"}, function(e){
  alert(e.data.name + " 按了按鈕!");     //顯示 "Tony 按了按鈕"
  })

如果要替元素綁定多個事件, 可以用鏈式呼叫 on(), 例如 :

$("#btn").on("click", function(e){
  console.log("按了按鈕!");
  }).on("mouseover", function(e){
  console.log("滑鼠滑過按鈕!");
  });

也可以用事件雜湊來一次綁定多個事件 (為了可讀性可將事件處理函式命名), 例如 :

var eh1=function(e){console.log("按了按鈕!");};
var eh2=function(e){console.log("滑過按鈕!");};
$("#btn").on({click: eh1, mouseover: eh2});     // 鍵用字串 "click": eh1 也可以

傳遞資料的範例如下 (注意, data 是放在第二參數) :

var eh1=function(e){console.log(e.data.name + "按了按鈕!");};
var eh2=function(e){console.log("滑過按鈕!");};
$("#btn").on({click: eh1, mouseover: eh2},{"name":"Tony"});

事件物件 e 常用的屬性除 data 外還有表示滑鼠位置的 pageX 與 pageY; 常用方法有停止元素預設動作 (例如表單元素 form 之提交, 超連結元素 a 的重導向, 或核取方塊狀態之變化等) 的 preventDefault() 與停止事件沿 DOM 樹向上傳遞的 stopPropagation(). 典型的範例是以超連結當按鈕使用時, 必須於事件處理函式結尾以 return false 避免除新載入頁面, 這與連續呼叫 preventDefault() 與 stopPropagation() 效果相同.

有些情況需要取消事件綁定, 這可用呼叫 off() 達成, 其 API 如下 :

obj.off(eventType [, selector] [, handler])
obj.off(eventsHash [, selector]])

例如 :

$("#btn").off("click mouseover");


9. 用 Ajax 取得遠端網頁或資料 : 

Ajax 必須有後端伺服器配合才行, 在本機無法運作. jQuery 的 Ajax 函式與方法主要是由頂層函數 $.ajax(), 頂層捷徑函數 $.get(), $.post 與 $.getJSON(), 以及 jQuery 物件方法 obj.load() 構成, 其中 $.ajax() 是最底層函數, 其它函數與方法均以 $.ajax() 為基礎.

呼叫 $.ajax() 時必須傳入一個設定物件, 主要屬性與方法如下 :


 $.ajax() 常用屬性 說明
 url HTTP 請求的目標網址 (字串)
 type HTTP 請求的方式 ("GET" 或 "POST"), 預設為 "GET"
 data 請求附帶的參數資料, 可用物件 {a:1, b: 2} 或字串例如 "a=1&b=2"
 dataType 預期伺服器回應的資料類型字串 (text/html/xml/json/script/jsonp)
 success 請求成功時要執行之回呼函數, function(data, textStatus)
 error 請求失敗時要執行之回呼函數, function(XMLHttpRequest, textStatus)
 complete 請求送出時要執行之回呼函數, function(XMLHttpRequest, textStatus)
 beforeSend 請求送出前要執行之回呼函數, function(XMLHttpRequest)
 cache 是否在記憶體快取此結果 (布林值), 預設為 true 


伺服端的 Ajax 回應資料會傳入 success 屬性值的回呼函數參數 data 中, 例如載入遠端伺服器上的 HTML 檔 test.htm 時, 可將回應網頁從回呼函數參數 data 中取出後用 html() 方法填入 id=result 的指定元素內容中 :

$.ajax({
  type: "GET",
  url: "test.htm",
  dataType: "html",
  success: function(data) {
    $("#result").html(data);
    },
  error: function(xhr) {
    alert(xhr.status);
    }   
  });

動態網頁需要傳遞參數給伺服端的程式處理, 傳遞參數通常用 POST 方式將參數放在 HTTP 的 body 中傳送, 也可以用 GET 方式放在 HTTP 標頭中傳遞. 參數可以附在 url 屬性後面以查詢字串方式傳遞; 也可以用鍵值對方式放在 data 屬性中傳遞, 後端程式擷取 HTTP 參數的方式以 PHP 而言可用 $_GET[] 或 $_POST[] 取得, 但要視參數是放在 url 或 data 屬性而定 :
  • type=GET :
    不論 url 或 data 的參數一律轉成查詢字串在標頭中傳送, 後端要用 $_GET[] 擷取參數. 
  • type=POST :
    url 參數在標頭中傳送, 用 $_GET[] 擷取; data 參數在本體中傳送, 用 $_POST[] 擷取.
但不管傳遞方式為何, 後端程式用 $_REQUEST[] 都可以取出所傳遞的參數, 例如 :

$.ajax({
  type: "POST",
  url: "test.php",
  dataType: "html",
  data: {user: "tony", pwd: 123},
  success: function(data) {
    $("#result").html(data);
    },
  error: function(xhr) {
    alert(xhr.status);
    }   
  });

回應 HTML 資料的後端 PHP 範例如下 (注意 header) :

<?php
header("Content-Type: text/html; charset: utf-8");
echo "<p>get :user=".$_GET['user'].", pwd=".$_GET['pwd']."</p>".
     "<p>post : user=".$_POST['user'].", pwd=".$_POST['pwd']."</p>".
     "<p>post : user=".$_REQUEST['user'].", pwd=".$_REQUEST['pwd']."</p>".
     "<p style='font-weight:bold;'>Hello World!</p>".
     "<p id='normal'>Hello World!</p>";
?>

實際應用上是將表單元素之輸入值提交給後端伺服器, 表單元素 form 的 jQuery 物件有一個 serialize() 方法可將表單內有 name 屬性的元件輸入值轉成查詢字串, 例如下列登入表單 :

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

可用 $("#login_form").serialize() 將表單內的輸入元件值轉成 "user=tony&pwd=12345" 的查詢字串傳遞到後端, 例如 :

$.ajax({
  type: "POST",
  url: "test.php",
  dataType: "html",
  data: $("#login_form").serialize(),
  success: function(data) {
    $("#result").html(data);
    },
  error: function(xhr) {
    alert(xhr.status);
    } 
  });

除了 $.ajax() 外 jQuery 還提供較高階的捷徑函數, 較常用的是這三個 :
  • $.get() : 以 GET 方法取得遠端伺服器檔案
  • $.post() : 以 POST 方法取得遠端伺服器檔案
  • $.getJSON() : 以 POST 方法取得遠端伺服器 JSON 檔案
這些都是以 $.ajax() 為基礎包裝的捷徑函數. 例如 :

$.get({
  url: "test.php",
  dataType: "html",
  data: $("#login_form").serialize(),
  success: function(data) {
    $("#result").html(data);
    }   
  });

呼叫 $.post() 則以 POST 方式發出請求 :

$.post({
  url: "test.php",
  dataType: "html",
  data: $("#login_form").serialize(),
  success: function(data) {
    $("#result").html(data);
    }   
  });

若僅僅是查詢資料, 伺服端更精簡的方式是直接回應 JSON 資料再填入網頁內, 例如 :

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

回應此資料之後端程式 test_json.php 如下 :

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

用 POST 查詢 JSON 資料 :

$.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);
    }
  });

用捷徑函數 $.getJSON() 請求 JSON 資料 :

$.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);
    }
  });

詳細測試參考 :

測試 jQuery 的 Ajax 函數 $.ajax()
jQuery 的 Ajax 捷徑函數測試
測試 jQuery 的 Ajax 方法 load()


三. 工具函數 (utilities) :

jQuery 的工具函數是定義在頂層命名空間的函數, 而非任何 jQuery 物件之方法, 因此可用 jQuery. 或 $. 直接呼叫, 以下是較常用的函數 :


1. 迭代 (迴圈) 函數 $.each() : 

此函數可用來迭代陣列與物件, 但不能用來迭代字串中的字元 (迭代字串要用 for in 或 for of).

$.each(array/object, function(key/index, value))
第一個參數是要迭代的陣列或物件, 第二個參數是處理迭代過程的回呼函數. 回呼函數的第一參數是陣列的索引或物件的屬性 (鍵), 第二參數是元素或屬性之值. $.each() 的主要作用場域是在回呼函數而非傳回值, 其傳回值為第一參數 (即被跌代的物件或陣列).

陣列的迭代範例如下 :

var arr=["a", "b", "c"];
$.each(arr, function(idx, value){
  document.write("arr[" + idx + "]=" + value + ", "); 
  });

結果輸出 arr[0]=a, arr[1]=b, arr[2]=c,.

物件迭代的範例如下 :

var obj={name:"tony", gender:"male", age:18};
$.each(obj, function(key, value){
  document.write("obj." + key + "=" + value + ", "); 
  });

結果輸出 obj.name=tony, obj.gender=male, obj.age=18,.


2. 陣列過濾函數 $.grep() : 

此函數用來過濾陣列中的元素, 它有 1~3 個可能參數, 傳回值為一個陣列, API 如下 :

var arr=$.grep(array, function(value [, index]) [, invert]) {})

第一個參數是要過濾的陣列, 第二參數是負責過濾的回呼函數, 其第一參數為陣列之元素值, 第二可選參數為其索引, 第三參數為布林值, 預設為 false (正向過濾).

在迭代陣列中的每一個元素時, 回呼函數必須用條件運算傳回 true 或 false, 如果傳回 true, 則此元素會被 $.grep() 傳回給接收陣列 arr; 否則不會被傳回, 此即正向過濾功能. 若回呼函數第三參數 invert 傳入 true 則剛好相反, 即只有回呼函數傳回 false 時將元素回傳給接收陣列 (反向過濾), 範例如下 :

var arr1=[34,78,99,84,56,22,100];
var arr2=$.grep(arr1, function(value){ //過濾元素值
  return value >= 60;   //傳回及格分數 arr2=[78,99,84,100]
  });
var arr3=$.grep(arr1, function(value, index, true){ //過濾元素值
  return value >= 60;   //傳回不及格分數 arr3=[34,56,22]
  });


3. 陣列或物件用 $.map() 轉換 :

此函數可在迭代陣列元素或物件屬性的過程中, 於回呼函數裏透過運算傳回新陣列元素, 傳回值為一個陣列, API 如下 :

var arr=$.map(array/object, function(value [, index/attr]){})

第一參數為待轉換陣列或物件, 第二參數為回呼函數, 回呼函數的第一參數為陣列元素或物件屬性之值, 備選之第二參數為索引或屬性 (鍵). 此函數 API 與功能與 $.grep() 很像, 都是傳回一個陣列, 差別在於 $.grep() 回呼函數利用 return true/false 來控制要不要傳回原陣列元素, 而 $.map() 回呼函數中的 return 是直接傳回新陣列元素值, 例如 :

var score=[34,78,99,84,56,22,100];
var arr=$.map(score, function(value){
  return value < 60 ? value + 5 : value;     //不及格分數加 5 分後傳回
  });

結果傳回新陣列 arr=[39,78,99,84,61,27,100]. 如果傳回 null 則新陣列不會增加新元素, 例如 :

var score=[34,78,99,84,56,22,100];
var arr=$.map(score, function(value){
  return value < 60 ? null : value;     //傳回及格者分數
  });

結果傳回新陣列 arr=[78,99,84,100].


4. 陣列合併函數 $.merge() :

此函數可合併兩個陣列, 其 API 如下 :

var arr=$.merge(array1, array2)
合併後的新陣列為 array1 並且被傳回, 而 array2 則不變, 例如 :

var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3=$.merge(arr1, arr2);

合併後 arr1 與傳回值 arr3 結果都是 [1,2,3,4,5,6], 而 arr2 仍為 [4,5,6] 不變.


5. 用 $.inArray() 檢查陣列中是否含有特定元素 :

函數 $.inArray() 之 API 如下 :

var idx=$.inArray(value, array [, fromIndex])

第一參數為要檢查之元素, 第二參數為陣列, 可選之第三參數為開始檢查之索引 (預設 0), 如果有找到就傳回該元素之索引, 否則傳回 -1, 例如 :

var fruits=["apple", "grape", "guava"];
var idx=$.inArray("grape", fruits);          //陣列中有此元素, 傳回其索引 1
var idx=$.inArray("pineapple", fruits);   //陣列中無此元素, 傳回 -1

詳細測試請參考 :

jQuery 的工具函數測試


四. 實用範例 : 

以下摘要整理一些常用的實用範例.


1. 觸發滑鼠移動事件 (mousemove) 顯示座標 : 

此例網頁中有一 p 元素用來顯示滑鼠座標位置 :

<p></p>

當滑鼠移動時, 它會觸動 window 物件的 mousemove 事件, 可以利用事件物件之 pageX 與 pageY 屬性取得滑鼠位置之 (x, y) 座標 :

$(window).mousemove(function(e){
   $("p").html("X=" + e.pageX + " Y=" + e.pageY);
   });


參考 :

[Jquery] 複選的checkbox取值
[jQuery] checkbox 及 radio 設定值
[jQuery] select 元件的取值及給值
[Javascript/Jquery] 移除textarea中空行、空白行

沒有留言:

張貼留言