jQuery 屬性操作
jQuery 提供了多種方法來操作 HTML 元素的屬性,包括 HTML 屬性、DOM 屬性、表單值以及自訂資料。
HTML 屬性 vs DOM 屬性
在深入之前,需要先了解 HTML 屬性(attribute)和 DOM 屬性(property)的差異:
- HTML 屬性:定義在 HTML 標籤上的屬性,如
<input type="text" value="hello"> - DOM 屬性:JavaScript DOM 物件的屬性,反映元素的當前狀態
對於大多數屬性,兩者的值是相同的。但對於某些屬性(如 checked、selected、disabled),兩者可能不同:
<input type="checkbox" checked />
// HTML 屬性 - 返回屬性的原始值
$('input').attr('checked'); // "checked"
// DOM 屬性 - 返回當前狀態
$('input').prop('checked'); // true 或 false
attr() - HTML 屬性
取得屬性值
// 取得 href 屬性
var url = $('a').attr('href');
// 取得 src 屬性
var src = $('img').attr('src');
// 取得自訂屬性
var id = $('#item').attr('data-id');
設定屬性值
// 設定單一屬性
$('a').attr('href', 'https://example.com');
$('img').attr('alt', '圖片說明');
// 設定多個屬性
$('a').attr({
href: 'https://example.com',
title: '前往範例網站',
target: '_blank',
});
// 使用函式設定
$('a').attr('href', function (index, oldValue) {
return oldValue + '?ref=site';
});
使用場景
attr() 適合用於:
- 取得/設定 href、src、title、alt 等屬性
- 取得/設定 data-* 自訂屬性
- 取得/設定 ARIA 屬性
removeAttr() - 移除屬性
// 移除單一屬性
$('a').removeAttr('target');
// 移除多個屬性(空格分隔)
$('input').removeAttr('disabled readonly');
prop() - DOM 屬性
取得屬性值
// 取得 checkbox 是否被勾選
var isChecked = $('input[type="checkbox"]').prop('checked');
// 取得 input 是否被停用
var isDisabled = $('input').prop('disabled');
// 取得 select option 是否被選取
var isSelected = $('option').prop('selected');
設定屬性值
// 勾選 checkbox
$('input[type="checkbox"]').prop('checked', true);
// 停用 input
$('input').prop('disabled', true);
// 設定多個屬性
$('input').prop({
disabled: true,
readonly: true,
});
// 使用函式設定
$('input[type="checkbox"]').prop('checked', function (index, oldValue) {
return !oldValue; // 切換勾選狀態
});
使用場景
prop() 適合用於:
- checked(checkbox、radio 的勾選狀態)
- selected(option 的選取狀態)
- disabled(表單元素的停用狀態)
- readonly(表單元素的唯讀狀態)
- selectedIndex(select 的選取索引)
- tagName、nodeName(元素標籤名)
attr() vs prop() 比較
| 情境 | 使用方法 | 說明 |
|---|---|---|
| href、src、title | attr() | HTML 屬性 |
| checked、disabled、selected | prop() | 反映當前狀態 |
| data-* 屬性 | attr() 或 data() | 自訂資料 |
| class | attr() 或 addClass() 等 | 建議用專門方法 |
| style | attr() 或 css() | 建議用 css() |
| value(取得當前值) | val() | 表單值 |
實際差異示範
<input type="checkbox" checked />
// 初始狀態
$('input').attr('checked'); // "checked"
$('input').prop('checked'); // true
// 使用者取消勾選後
$('input').attr('checked'); // "checked"(HTML 屬性不變)
$('input').prop('checked'); // false(反映當前狀態)
最佳實踐:操作布林屬性(checked、disabled、selected 等)時,應使用
prop(),因為它能正確反映元素的當前狀態。removeProp() - 移除 DOM 屬性
移除使用 prop() 設定的屬性:
$('input').removeProp('disabled');
注意:
removeProp() 不應用於移除原生的 DOM 屬性(如 checked、disabled),這樣做可能導致無法再次設定這些屬性。應改用 prop('disabled', false) 來停用屬性效果。val() - 表單值
val() 方法用於取得或設定表單元素的值。
取得值
// 取得 input 值
var username = $('#username').val();
// 取得 textarea 值
var message = $('#message').val();
// 取得 select 的選取值
var country = $('#country').val();
// 取得多選 select 的所有選取值(返回陣列)
var languages = $('#languages').val();
// ['javascript', 'python', 'php']
// 取得 radio 的選取值
var gender = $('input[name="gender"]:checked').val();
// 取得 checkbox 的值(需先確認是否勾選)
var agree = $('#agree').prop('checked') ? $('#agree').val() : '';
// 取得所有已勾選 checkbox 的值
var hobbies = $('input[name="hobby"]:checked')
.map(function () {
return $(this).val();
})
.get();
設定值
// 設定 input 值
$('#username').val('John');
// 設定 textarea 值
$('#message').val('Hello World');
// 設定 select 的選取值
$('#country').val('tw');
// 設定多選 select 的選取值
$('#languages').val(['javascript', 'python']);
// 設定 radio 的選取值
$('input[name="gender"]').val(['male']);
// 設定多個 checkbox 的勾選(使用陣列)
$('input[name="hobby"]').val(['reading', 'sports']);
// 使用函式設定
$('input').val(function (index, oldValue) {
return oldValue.toUpperCase();
});
data() - 自訂資料
jQuery 提供 data() 方法來儲存與元素相關的任意資料。
HTML5 data-* 屬性
<div id="user" data-id="123" data-user-name="John" data-active="true"></div>
// 讀取 data-* 屬性
$('#user').data('id'); // 123(自動轉為數字)
$('#user').data('userName'); // "John"(camelCase 轉換)
$('#user').data('active'); // true(自動轉為布林值)
// 讀取所有 data-* 屬性
$('#user').data();
// {id: 123, userName: "John", active: true}
data() 會自動將屬性名稱從 kebab-case(data-user-name)轉換為 camelCase(userName)。儲存資料
// 儲存簡單值
$('#item').data('price', 99);
$('#item').data('inStock', true);
// 儲存物件
$('#item').data('info', {
name: 'Product',
category: 'Electronics',
});
// 儲存陣列
$('#item').data('tags', ['sale', 'popular']);
// 讀取儲存的資料
var price = $('#item').data('price'); // 99
var info = $('#item').data('info'); // {name: 'Product', ...}
var name = $('#item').data('info').name; // 'Product'
data() vs attr('data-*')
// 使用 data() 設定的資料不會反映到 HTML 屬性
$('#item').data('key', 'value');
$('#item').attr('data-key'); // undefined(除非原本就有)
// 使用 attr() 設定會更新 HTML 屬性
$('#item').attr('data-key', 'value');
$('#item').data('key'); // 'value'
| 方法 | 讀取來源 | 寫入位置 | 資料類型轉換 |
|---|---|---|---|
data() | HTML data-* 屬性 + jQuery 內部快取 | jQuery 內部快取 | 自動 |
attr('data-*') | HTML data-* 屬性 | HTML data-* 屬性 | 無(總是字串) |
removeData() - 移除資料
// 移除特定資料
$('#item').removeData('price');
// 移除所有透過 data() 儲存的資料
$('#item').removeData();
removeData() 只會移除透過 data() 方法儲存的資料,不會移除 HTML 的 data-_ 屬性。若要移除 HTML 屬性,請使用 removeAttr('data-_')。實用範例
切換按鈕狀態
$('#submit').on('click', function () {
var $btn = $(this);
// 停用按鈕並顯示載入中
$btn.prop('disabled', true).text('處理中...');
// 模擬 Ajax 完成後恢復
setTimeout(function () {
$btn.prop('disabled', false).text('送出');
}, 2000);
});
全選/取消全選
$('#selectAll').on('change', function () {
var isChecked = $(this).prop('checked');
$('input[name="item"]').prop('checked', isChecked);
});
// 更新全選狀態
$('input[name="item"]').on('change', function () {
var total = $('input[name="item"]').length;
var checked = $('input[name="item"]:checked').length;
$('#selectAll').prop('checked', total === checked);
});
動態設定連結
$('.download-btn').each(function () {
var $btn = $(this);
var fileId = $btn.data('fileId');
var fileName = $btn.data('fileName');
$btn.attr({
href: '/download/' + fileId,
download: fileName,
});
});
表單資料收集
$('form').on('submit', function (e) {
e.preventDefault();
var formData = {
username: $('#username').val(),
email: $('#email').val(),
gender: $('input[name="gender"]:checked').val(),
country: $('#country').val(),
interests: $('input[name="interest"]:checked')
.map(function () {
return $(this).val();
})
.get(),
agree: $('#agree').prop('checked'),
};
console.log(formData);
});