Zepto.js — это минималистичная библиотека, ориентированная на работу с современными браузерами, которая предлагает знакомый интерфейс, похожий на jQuery. Несмотря на компактность, она обеспечивает возможность работы с методами, которые могут отсутствовать в старых браузерах. Для этого используются полифиллы и замены стандартных методов JavaScript.
Zepto активно использует массивоподобные объекты для работы с
DOM-элементами. В некоторых старых браузерах отсутствуют методы
forEach, map, filter для
NodeList. Zepto реализует собственные обходы коллекций:
Zepto.isArrayLike = function(obj) {
var length = !!obj && 'length' in obj && obj.length,
type = $.type(obj);
return 'function' != type && !$.isWindow(obj) && (
'array' === type || length === 0 ||
(typeof length === 'number' && length > 0 && (length - 1) in obj)
);
};
$.each = function(elements, callback){
var i, key;
if (isArrayLike(elements)) {
for (i = 0; i < elements.length; i++)
if (callback.call(elements[i], i, elements[i]) === false) return elements;
} else {
for (key in elements)
if (callback.call(elements[key], key, elements[key]) === false) return elements;
}
return elements;
};
$.each служит универсальным полифиллом обхода, заменяя
стандартный Array.prototype.forEach там, где он
недоступен.
querySelectorAll и getElementsByClassNameZepto поддерживает поиск элементов через CSS-селекторы, используя
querySelectorAll там, где это возможно, но предоставляет
альтернативы для браузеров, где метод отсутствует:
zepto.qsa = function(element, selector){
return element.querySelectorAll(selector);
};
Для старых браузеров возможно использование обхода дочерних элементов
с проверкой соответствия селектору. В Zepto это реализовано через
внутренние функции типа matches:
var el = document.createElement('div');
if (!el.matches) {
el.matches = el.msMatchesSelector || el.webkitMatchesSelector;
}
Так обеспечивается корректная работа селекторов в Internet Explorer 9+ и старых WebKit.
События являются критическим аспектом кроссбраузерности. Zepto
заменяет методы addEventListener и
removeEventListener там, где они отсутствуют, и добавляет
полифиллы для input, change,
focusin/focusout:
$.Event = function(type, props) {
if (!(this instanceof $.Event)) return new $.Event(type, props);
var event = document.createEvent('Events');
event.initEvent(type, true, true);
if (props) $.extend(event, props);
return event;
};
Эта конструкция обеспечивает создание событий, совместимых со старыми
браузерами, включая IE8, где отсутствует стандартный конструктор
Event.
Для делегирования событий используется $.proxy:
$.proxy = function(fn, context) {
return function() {
return fn.apply(context, arguments);
};
};
Это позволяет сохранять контекст this при обработке
событий, что критично для старых реализаций DOM API.
Zepto реализует легковесный интерфейс для AJAX-запросов через
$.ajax, автоматически проверяя наличие
XMLHttpRequest. Для старых браузеров используется
ActiveX:
$.ajaxSettings = {
type: 'GET',
beforeSend: function(){},
success: function(){},
error: function(){},
complete: function(){}
};
$.ajax = function(options){
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open(options.type, options.url, true);
xhr.onreadystatecha nge = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) options.success(xhr.responseText, xhr.status, xhr);
else options.error(xhr, xhr.status, xhr.statusText);
options.complete(xhr, xhr.status);
}
};
xhr.send(options.data || null);
};
Такой подход обеспечивает работу AJAX даже в старых версиях IE,
заменяя современный fetch.
Zepto имеет собственный модуль анимаций через
$.fn.animate. В старых браузерах, где отсутствует
requestAnimationFrame, используется замена через
setTimeout:
window.requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback){ return setTimeout(callback, 16); };
Аналогично, для свойств CSS с префиксами (например,
transform), Zepto применяет динамическое определение:
var vendors = ['webkit', 'Moz', 'O', 'ms'];
function prefixed(prop) {
var style = document.createElement('div').style;
if (prop in style) return prop;
var capitalized = prop.charAt(0).toUpperCase() + prop.slice(1);
for (var i = 0; i < vendors.length; i++) {
var vendorProp = vendors[i] + capitalized;
if (vendorProp in style) return vendorProp;
}
return prop;
}
Это позволяет корректно изменять стиль элементов без опасений, что метод будет недоступен в браузере пользователя.
Zepto добавляет полифиллы для функций Object.keys и
JSON.stringify:
if (!Object.keys) {
Object.keys = function(obj) {
var keys = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) keys.push(key);
}
return keys;
};
}
if (!window.JSON) {
window.JSON = {
stringify: function(obj) { /* упрощённая реализация */ },
parse: function(str) { /* упрощённая реализация */ }
};
}
Это обеспечивает совместимость с очень старыми браузерами без современных методов работы с объектами и сериализации данных.
Полифиллы и замены в Zepto позволяют:
Zepto сочетает минимальный размер с широким охватом браузерной совместимости благодаря грамотно реализованным внутренним заменам и полифиллам.