jQuery数据存储是一种在DOM元素上存储和检索任意数据的方法。它使用内存缓存来存储数据,避免了直接修改DOM属性,提供了更好的性能和灵活性。
.data()方法data-*属性.attr()方法| 方法 | 描述 | 返回值 | 是否支持链式 | 推荐程度 |
|---|---|---|---|---|
.data(key, value) |
存储数据到元素 | jQuery对象 | 是 | |
.data(key) |
从元素获取数据 | 存储的值 | 否 | |
.data() |
获取所有数据 | 对象 | 否 | |
.removeData(key) |
移除指定数据 | jQuery对象 | 是 | |
.removeData() |
移除所有数据 | jQuery对象 | 是 | |
.attr('data-*', value) |
设置data属性 | jQuery对象 | 是 | |
.metadata() |
解析metadata插件(已弃用) | 对象 | 否 |
// 存储单个值
$('#element').data('username', 'john_doe');
// 存储多个值(对象形式)
$('#element').data({
id: 123,
name: 'John Doe',
email: 'john@example.com',
settings: {
theme: 'dark',
notifications: true
}
});
// 存储复杂数据类型
$('#element').data('callback', function() {
console.log('这是一个函数');
});
// 存储数组
$('#element').data('items', [1, 2, 3, 4, 5]);
// 存储DOM元素
$('#element').data('relatedElement', document.getElementById('other'));
// 读取单个值
var username = $('#element').data('username');
console.log(username); // 'john_doe'
// 读取对象属性(自动展开)
var id = $('#element').data('id');
var name = $('#element').data('name');
var email = $('#element').data('email');
// 读取嵌套对象
var theme = $('#element').data('settings').theme;
// 读取函数并执行
var callback = $('#element').data('callback');
if (typeof callback === 'function') {
callback(); // 输出: '这是一个函数'
}
// 获取所有数据
var allData = $('#element').data();
console.log(allData); // {username: 'john_doe', id: 123, ...}
// 移除单个数据项
$('#element').removeData('username');
// 移除多个数据项
$('#element').removeData('id name email');
// 移除所有数据
$('#element').removeData();
// 链式操作
$('#element')
.removeData('username')
.addClass('updated')
.fadeOut();
// 检查数据是否存在后再移除
if ($('#element').data('username') !== undefined) {
$('#element').removeData('username');
}
// 批量移除(遍历)
$('.items').each(function() {
$(this).removeData();
});
<!-- 在HTML中定义data属性 -->
<div id="product"
data-id="123"
data-name="智能手机"
data-price="2999.99"
data-stock="true"
data-specs='{"color":"black","memory":"128GB"}'>
产品信息
</div>
<!-- 动态生成的data属性 -->
<button data-action="save"
data-confirm="确定保存吗?"
data-url="/api/save">
保存
</button>
<!-- 使用CSS选择data属性 -->
<style>
[data-role="dialog"] {
display: none;
position: fixed;
z-index: 1000;
}
[data-theme="dark"] {
background-color: #333;
color: white;
}
</style>
// 读取data属性
var id = $('#product').data('id'); // 123 (自动转换为数字)
var name = $('#product').data('name'); // '智能手机'
var price = $('#product').data('price'); // 2999.99 (自动转换为数字)
var stock = $('#product').data('stock'); // true (自动转换为布尔值)
var specs = $('#product').data('specs'); // {color: 'black', memory: '128GB'} (自动解析JSON)
// 设置data属性(不修改HTML,只在内存中)
$('#product').data('discount', 0.2);
// 通过.data()设置会更新内存,但不会更新HTML属性
// 通过.attr()设置会更新HTML属性
$('#product').attr('data-discount', '0.2');
// 批量读取
var allData = $('#product').data();
console.log(allData);
// 注意:data()方法会自动转换数据类型
// 而attr()方法总是返回字符串
var id1 = $('#product').data('id'); // 123 (数字)
var id2 = $('#product').attr('data-id'); // '123' (字符串)
.data()方法0ms
0ms
.attr()方法0ms
jQuery使用内部的$.cache对象存储数据,每个DOM元素对应一个唯一ID。
.data()方法会自动转换数据类型:字符串"123"→数字123,"true"→布尔值true,JSON字符串→对象。
当DOM元素被移除时,jQuery会自动清理对应的缓存数据,防止内存泄漏。
// 为每个商品存储详细信息
$('.product-item').each(function() {
var $product = $(this);
var id = $product.data('id');
var name = $product.data('name');
var price = $product.data('price');
$product.on('click', function() {
// 添加到购物车
addToCart({
id: id,
name: name,
price: price,
quantity: 1
});
// 标记为已添加
$product.data('inCart', true)
.addClass('in-cart');
});
// 检查是否已在购物车中
if ($product.data('inCart')) {
$product.addClass('in-cart');
}
});
// 更新商品数量
function updateQuantity($product, newQuantity) {
$product.data('quantity', newQuantity);
$product.find('.quantity').text(newQuantity);
}
// 为每个消息存储元数据
function addMessage(message) {
var $message = $('<div class="message">')
.text(message.text)
.data({
id: message.id,
timestamp: message.timestamp,
sender: message.sender,
status: 'sent',
readBy: []
})
.appendTo('#chat-container');
// 为消息添加交互
$message.on('click', function() {
var $msg = $(this);
var status = $msg.data('status');
var id = $msg.data('id');
if (status === 'sent') {
$msg.data('status', 'read')
.addClass('read');
// 通知服务器消息已读
markAsRead(id);
}
});
// 右键菜单
$message.on('contextmenu', function(e) {
e.preventDefault();
showMessageMenu($(this).data());
});
}
// 批量更新消息状态
function markAllAsRead() {
$('.message').each(function() {
var $msg = $(this);
if ($msg.data('status') === 'sent') {
$msg.data('status', 'read')
.addClass('read');
}
});
}
// 为UI组件存储状态
$.fn.accordion = function(options) {
return this.each(function() {
var $accordion = $(this);
var $headers = $accordion.find('.accordion-header');
var $contents = $accordion.find('.accordion-content');
// 初始化数据
$accordion.data('accordion', {
options: $.extend({}, options),
activeIndex: -1,
speed: 300
});
$headers.each(function(index) {
var $header = $(this);
var $content = $contents.eq(index);
// 存储关联关系
$header.data({
accordion: $accordion,
content: $content,
index: index
});
$header.on('click', function() {
var $hdr = $(this);
var $content = $hdr.data('content');
var $acc = $hdr.data('accordion');
var accData = $acc.data('accordion');
var index = $hdr.data('index');
// 切换展开/折叠
if (accData.activeIndex === index) {
$content.slideUp(accData.speed);
accData.activeIndex = -1;
} else {
// 关闭其他
if (accData.activeIndex !== -1) {
$contents.eq(accData.activeIndex)
.slideUp(accData.speed);
}
$content.slideDown(accData.speed);
accData.activeIndex = index;
}
// 更新数据
$acc.data('accordion', accData);
});
});
});
};
// 使用数据存储增强事件委托
$('#product-list').on('click', '.product', function() {
var $product = $(this);
var productData = $product.data();
// 使用存储的数据
showProductDetails({
id: productData.id,
name: productData.name,
price: productData.price,
category: productData.category
});
});
// 动态添加产品时自动获取数据
function addProduct(product) {
var $product = $('<div class="product">')
.text(product.name)
.data(product) // 存储所有产品数据
.appendTo('#product-list');
// 不需要单独绑定事件!
}
// 创建数据存取器插件
$.fn.store = function(key, value) {
if (arguments.length === 2) {
// 设置值
return this.data('store_' + key, value);
} else if (typeof key === 'object') {
// 批量设置
var self = this;
$.each(key, function(k, v) {
self.data('store_' + k, v);
});
return this;
} else if (key === undefined) {
// 获取所有
var data = {};
var allData = this.data();
$.each(allData, function(k, v) {
if (k.indexOf('store_') === 0) {
data[k.substring(6)] = v;
}
});
return data;
} else {
// 获取单个
return this.data('store_' + key);
}
};
// 使用自定义存取器
$('#element').store('user', {name: 'John', age: 30});
var user = $('#element').store('user');
// 批量操作
$('#element').store({
settings: {theme: 'dark'},
preferences: {notifications: true}
});
// 监听数据变化
$.fn.watchData = function(key, callback) {
return this.each(function() {
var $element = $(this);
var currentValue = $element.data(key);
// 存储原始data方法
var originalData = $element.data;
// 重写data方法
$element.data = function(k, v) {
var result = originalData.apply(this, arguments);
// 检查是否是我们监听的key
if (k === key && arguments.length === 2) {
var oldValue = currentValue;
currentValue = v;
// 触发回调
callback.call(this, v, oldValue);
}
return result;
};
});
};
// 使用数据监听
$('#counter').watchData('count', function(newVal, oldVal) {
console.log('计数从', oldVal, '变为', newVal);
$(this).text('计数: ' + newVal);
});
// 修改数据时会触发监听
$('#counter').data('count', 10);
$('#counter').data('count', 20);
// 1. 查看所有元素的存储数据
function dumpAllData() {
$('*').each(function() {
var data = $(this).data();
if (Object.keys(data).length > 0) {
console.log('Element:', this);
console.log('Data:', data);
}
});
}
// 2. 数据存储监视器
$.fn.dataWatcher = function() {
return this.each(function() {
var $el = $(this);
var el = this;
// 记录原始方法
var originalData = $el.data;
var originalRemoveData = $el.removeData;
// 重写方法添加日志
$el.data = function() {
console.log('data() called on', el, 'with args:', arguments);
var result = originalData.apply(this, arguments);
console.log('Result:', result);
return result;
};
$el.removeData = function() {
console.log('removeData() called on', el, 'with args:', arguments);
return originalRemoveData.apply(this, arguments);
};
});
};
// 3. 内存使用统计
function getDataMemoryUsage() {
var total = 0;
$('*').each(function() {
var data = $(this).data();
var size = JSON.stringify(data).length;
total += size;
});
console.log('Total data storage:', (total / 1024).toFixed(2), 'KB');
return total;
}
// 4. 查找特定数据
function findDataByKey(key, value) {
var elements = [];
$('*').each(function() {
var data = $(this).data(key);
if (data === value) {
elements.push(this);
}
});
return elements;
}
A: .data()存储在内存中,支持复杂数据类型,不修改DOM。.attr('data-*')修改DOM属性,只支持字符串。
A: 数据会一直存在直到:1) 调用removeData();2) 元素被从DOM中移除;3) 页面刷新。
A: 1) 及时清理不再需要的数据;2) 避免循环引用;3) 在元素移除前调用removeData();4) 使用弱引用存储大对象。