Mô-đun Data trong Zepto được sử dụng để lấy dữ liệu từ các thuộc tính data-* của các nút DOM và lưu trữ thông tin liên quan đến DOM.
Phiên bản mã nguồn
Bài viết này dựa trên mã nguồn Zepto phiên bản 1.2.0.
Hàm nội bộ
attributeData
var dataStore = {}, dataAttribute = $.fn.data, convertToCamelCase = $.camelCase,
uniqueKey = $.expando = 'Zepto' + (+new Date()), emptyList = [];
function extractDataAttributes(element) {
var storage = {};
$.each(element.attributes || emptyList, function(index, attribute) {
if (attribute.name.startsWith('data-'))
storage[convertToCamelCase(attribute.name.slice(5))] =
$.zepto.deserializeValue(attribute.value);
});
return storage;
}
Hàm này thu thập tất cả các thuộc tính data-* từ một phần tử cụ thể và lưu vào đối tượng storage.
Trong quá trình duyệt qua các thuộc tính của phần tử, chỉ những thuộc tính có tên bắt đầu bằng data- mới được xử lý.
Khi lưu trữ, phần data- sẽ bị loại bỏ khỏi tên thuộc tính, phần còn lại được chuyển đổi sang dạng camel case để sử dụng làm khóa cho đối tượng storage.
Vì giá trị thuộc tính trong DOM đều là chuỗi, nên hàm deserializeValue được gọi để chuyển đổi giá trị thành kiểu dữ liệu tương ứng.
setData
function setElementData(element, key, value) {
var identifier = element[uniqueKey] || (element[uniqueKey] = ++$.uuid),
storage = dataStore[identifier] || (dataStore[identifier] = extractDataAttributes(element));
if (key !== undefined) storage[convertToCamelCase(key)] = value;
return storage;
}
Để giảm bớt việc truy cập vào DOM, hàm setData lưu trữ dữ liệu trong bộ nhớ.
Đầu tiên, hàm tìm kiếm thuộc tính uniqueKey trên phần tử. Nếu không tồn tại, nó sẽ được tạo ra.
Sau đó, nó tìm kiếm dữ liệu đã được lưu trước đó trong đối tượng dataStore. Nếu không có dữ liệu nào được lưu, nó sẽ gọi hàm extractDataAttributes để thu thập các thuộc tính data-* từ phần tử.
Cuối cùng, nó gán giá trị cần lưu vào vị trí tương ứng trong đối tượng storage.
getData
function getElementData(element, key) {
var identifier = element[uniqueKey], storage = identifier && dataStore[identifier];
if (key === undefined) return storage || setElementData(element);
else {
if (storage) {
if (key in storage) return storage[key];
var camelKey = convertToCamelCase(key);
if (camelKey in storage) return storage[camelKey];
}
return dataAttribute.call($(element), key);
}
}
Hàm này lấy dữ liệu đã được lưu từ một phần tử cụ thể.
Nếu không cung cấp khóa, hàm sẽ trả về tất cả các dữ liệu đã lưu. Nếu không có dữ liệu nào, nó sẽ gọi hàm setElementData để thu thập các thuộc tính data-*.
Nếu khóa được cung cấp, hàm sẽ kiểm tra xem khóa có tồn tại trong đối tượng storage hay không. Nếu không, nó sẽ thử tìm khóa dưới dạng camel case.
Nếu vẫn không tìm thấy, hàm sẽ sử dụng phương thức $.fn.data để tìm kiếm giá trị thuộc tính data-*.
Phương thức DOM
.data()
$.fn.data = function(key, value) {
return value === undefined ?
$.isPlainObject(key) ?
this.each(function(index, element) {
$.each(key, function(k, v) { setElementData(element, k, v) });
}) :
(this.length > 0 ? getElementData(this[0], key) : undefined) :
this.each(function() { setElementData(this, key, value) });
};
Phương thức .data() dùng để lấy hoặc thiết lập dữ liệu cho các phần tử DOM.
Nếu chỉ cung cấp khóa, hàm sẽ trả về dữ liệu đã lưu của phần tử đầu tiên trong tập hợp. Nếu tập hợp rỗng, nó sẽ trả về undefined.
Nếu cung cấp cả khóa và giá trị, hàm sẽ thiết lập dữ liệu cho tất cả các phần tử trong tập hợp.
Ngoài ra, nếu khóa là một đối tượng, hàm sẽ lặp qua từng thuộc tính của đối tượng và thiết lập dữ liệu tương ứng cho từng phần tử.
.removeData()
$.fn.removeData = function(keys) {
if (typeof keys == 'string') keys = keys.split(/\s+/);
return this.each(function() {
var identifier = this[uniqueKey], storage = identifier && dataStore[identifier];
if (storage) $.each(keys || storage, function(key) {
delete storage[keys ? convertToCamelCase(key) : key];
});
});
};
Phương thức .removeData() dùng để xóa dữ liệu đã lưu.
Nếu không cung cấp khóa, hàm sẽ xóa tất cả các dữ liệu đã lưu. Nếu cung cấp khóa, chỉ dữ liệu tương ứng với khóa đó mới bị xóa.
Khóa có thể là một mảng chứa nhiều khóa cần xóa hoặc một chuỗi các khóa cách nhau bởi khoảng trắng.
.remove() và .empty()
;['remove', 'empty'].forEach(function(methodName) {
var originalMethod = $.fn[methodName];
$.fn[methodName] = function() {
var elements = this.find('*');
if (methodName === 'remove') elements = elements.add(this);
elements.removeData();
return originalMethod.call(this);
};
});
Khi xóa các phần tử DOM, dữ liệu đã lưu cũng cần được xóa để giải phóng bộ nhớ.
Hai phương thức .remove() và .empty() được mở rộng để tự động xóa dữ liệu sau khi xóa các phần tử.
Nếu gọi .remove(), cả phần tử được gọi và tất cả các phần tử con đều sẽ bị xóa. Nếu gọi .empty(), chỉ các phần tử con sẽ bị xóa.
Hàm tiện ích
$.data
$.data = function(element, key, value) {
return $(element).data(key, value);
};
Hàm $.data đơn giản chỉ gọi phương thức .data() của đối tượng jQuery.
$.hasData
$.hasData = function(element) {
var identifier = element[uniqueKey], storage = identifier && dataStore[identifier];
return storage ? !$.isEmptyObject(storage) : false;
};
Hàm $.hasData kiểm tra xem một phần tử có dữ liệu đã lưu hay không.
Nó tìm kiếm đối tượng storage tương ứng với phần tử trong đối tượng dataStore. Nếu tìm thấy và đối tượng không rỗng, hàm sẽ trả về true.