Zepto 实现原理
理解 Zepto 的架构设计和 $ 函数的实现方式
问题
Zepto 是一个轻量级的 JavaScript 库,API 与 jQuery 兼容。它的实现原理是什么?
解答
整体架构
Zepto 的核心是 $ 函数,它返回一个包含 DOM 元素的类数组对象,并通过原型链提供各种操作方法。
// 简化版 Zepto 实现
var Zepto = (function() {
var $, zepto = {};
// Zepto 对象构造函数
function Z(dom, selector) {
var len = dom ? dom.length : 0;
for (var i = 0; i < len; i++) {
this[i] = dom[i];
}
this.length = len;
this.selector = selector || '';
}
// 初始化方法
zepto.Z = function(dom, selector) {
return new Z(dom, selector);
};
// 判断是否为 Zepto 对象
zepto.isZ = function(object) {
return object instanceof Z;
};
// 核心:将选择器转换为 DOM 数组
zepto.qsa = function(element, selector) {
return Array.prototype.slice.call(
element.querySelectorAll(selector)
);
};
// 初始化入口
zepto.init = function(selector, context) {
var dom;
// 空选择器,返回空 Zepto 对象
if (!selector) {
return zepto.Z();
}
// 字符串选择器
if (typeof selector === 'string') {
selector = selector.trim();
// HTML 字符串,创建 DOM 元素
if (selector[0] === '<') {
dom = zepto.fragment(selector);
} else {
// CSS 选择器,查询 DOM
dom = zepto.qsa(context || document, selector);
}
}
// DOM 元素
else if (selector.nodeType) {
dom = [selector];
}
// 数组或类数组
else if (Array.isArray(selector)) {
dom = selector;
}
// Zepto 对象,直接返回
else if (zepto.isZ(selector)) {
return selector;
}
// 函数,DOM ready 后执行
else if (typeof selector === 'function') {
return $(document).ready(selector);
}
return zepto.Z(dom, selector);
};
// $ 函数
$ = function(selector, context) {
return zepto.init(selector, context);
};
// 原型方法挂载点
$.fn = {
constructor: zepto.Z,
length: 0,
// 遍历方法
each: function(callback) {
Array.prototype.every.call(this, function(el, idx) {
return callback.call(el, idx, el) !== false;
});
return this;
},
// 查找子元素
find: function(selector) {
var result = [];
this.each(function() {
var nodes = zepto.qsa(this, selector);
result = result.concat(Array.prototype.slice.call(nodes));
});
return zepto.Z(result, selector);
},
// 添加 class
addClass: function(name) {
return this.each(function() {
this.classList.add(name);
});
},
// 设置/获取 CSS
css: function(property, value) {
if (value === undefined) {
return this[0] && this[0].style[property];
}
return this.each(function() {
this.style[property] = value;
});
},
// 事件绑定
on: function(event, callback) {
return this.each(function() {
this.addEventListener(event, callback, false);
});
}
};
// 关键:将 $.fn 设为 Z 的原型
zepto.Z.prototype = Z.prototype = $.fn;
return $;
})();
// 暴露到全局
window.Zepto = Zepto;
window.$ = Zepto;
使用示例
// 选择元素
$('.item').addClass('active');
// 链式调用
$('#box')
.css('color', 'red')
.on('click', function() {
console.log('clicked');
});
// DOM ready
$(function() {
console.log('DOM 加载完成');
});
// 创建元素
$('<div class="new">新元素</div>').appendTo('body');
原型链结构
$('.item') 返回的对象
↓
Z 实例 { 0: element, 1: element, length: 2 }
↓ __proto__
$.fn (包含 each, find, css, on 等方法)
↓ __proto__
Object.prototype
关键点
- 类数组对象:Zepto 对象本质是包含 DOM 元素的类数组,有 length 属性和数字索引
- $ 函数多态:根据参数类型(字符串、DOM、函数、数组)执行不同逻辑
- 原型链设计:
$.fn作为所有 Zepto 对象的原型,方法定义在此处实现共享 - 链式调用:方法返回
this(Zepto 对象本身)实现链式操作 - 轻量化:相比 jQuery,Zepto 去掉了 IE 兼容代码,体积更小,适合移动端
目录