Zepto源码分析之二~三个API

由于时间关系:本次只对这三个API($.camelCase、$.contains、$.each)方法进行分析

第一个方法变量转驼峰:$.camelCase(‘hello-world-welcome‘);

源码:

var camelize;

/**

* 字符串替换

* 使用replace第二个参数带回调

*/

camelize = function(str) {

return str.replace(/-+(.)?/g,

function(match, chr) {

return chr ? chr.toUpperCase() : ‘‘;

}

);

};

/**

* 将一组字符串变成驼峰命名法

*/

$.camelCase = camelize;

第二个方法检查父节点是否包含给定的dom节点,如果两者是相同节点,返回false:$.contains(parent, node)

源码:

/**

* $.contains(parent, node);

* 检查父节点是否包含给定的dom节点,如果两者是相同节点,返回false

* return {boolean} true/false

*/

$.contains = document.documentElement.contains ?

function (parent, node) {

return parent !== node && parent.contains(node);

} :

function (parent, node) {

while (node && (node = node.parentNode)) {

if (node === parent) {

return true;

}

}

return false;

};

第三个方法遍历数组或以key-value值对方式遍历对象。回调函数返回false时停止遍历。

$.each(collection, function(index, item) { ... }) => collection

遍历数组元素或以key-value值对方式遍历对象。回调函数返回false时停止遍历。

$.each([‘a‘, ‘b‘, ‘c‘], function(index, item) {

console.log(‘item %d is: %s‘, index, item);

});

var hash = { name: ‘zepto.js‘, size: ‘micro‘ };

$.each(hash, function(key, value) {

console.log(‘%s: %s‘, key, value);

});

源码:

/**

* Zepto对象迭代器

* @param {object|array} elements 数据对象

* @param {function} callback 回调函数

* return {object|array} elements 数据对象

*/

$.each = function(elements, callback) {

var i;

var key;

// 数组检测

if (likeArray(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;

};

三个方法最后页面:demo.html

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="X-UA-Compatible" content="IE=Edge" />

<meta charset="utf-8" />

<title>Zepto源码分析</title>

<link rel="stylesheet" href="demo.css" type="text/css" />

</head>

<body>

<div id="test">

测试zepto源码

<span class="aa">22</span>

<span class="bb">2332</span>

</div>

<div class="wrap">content</div>

<script src="zepto-dev.js"></script>

<script>

console.log($(‘div‘));

console.log($(‘.aa‘));

console.log($(‘<div>这是测试内容</div>‘));

console.log($("<span />", { text: "测试测试111", id: "ceshi_111", css: { color: ‘red‘ } }));

Zepto(function($) {

console.log(‘Ready to Zepto!‘);

});

</script>

<script>

console.log($.camelCase(‘hello-there-body‘));

console.log($.contains($(‘#test‘)[0], $(‘.aa‘)[0]));

$.each([‘a‘, ‘b‘, ‘c‘], function(index, item) {

console.log(‘item %d is: %s‘, index, item);

});

var hash = { name: ‘zepto-dev.js‘, size: ‘micro‘ };

$.each(hash, function(key, value) {

console.log(‘%s: %s‘, key, value);

});

</script>

</body>

</html>

zepto-dev.js源码:

var Zepto = (function() {

/**

* 变量初始化

*/

var $;

var zepto = {};

var fragmentRE = /^\s*<(\w+|!)[^>]*>/;

var singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;

var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;

var undefined;

var emptyArray = [];

var slice = emptyArray.slice;

var cssNumber = {

‘column-count‘: 1,

‘columns‘: 1,

‘font-weight‘: 1,

‘line-height‘: 1,

‘opacity‘: 1,

‘z-index‘: 1,

‘zoom‘: 1

};

// 特殊属性集合

var methodAttributes = [ ‘val‘, ‘css‘, ‘html‘, ‘text‘, ‘data‘, ‘width‘, ‘height‘, ‘offset‘ ];

var table = document.createElement(‘table‘);

var tableRow = document.createElement(‘tr‘);

var containers = {

‘tr‘: document.createElement(‘tbody‘),

‘tbody‘: table,

‘thead‘: table,

‘tfoot‘: table,

‘td‘: tableRow,

‘th‘: tableRow,

‘*‘: document.createElement(‘div‘)

};

var readyRE = /complete|loaded|interactive/;

var simpleSelectorRE = /^[\w-]*$/;

var class2type = {};

var toString = class2type.toString;

var camelize;

var isArray = Array.isArray || function(object) {

return object instanceof Array;

};

/**

* 检测函数

*/

function type(obj) {

return obj == null ? String(obj) :

class2type[toString.call(obj)] || "object";

}

function isFunction(value) {

return type(value) == "function";

}

function isWindow(obj) {

return obj != null && obj == obj.window;

}

function isDocument(obj) {

return obj != null && obj.nodeType == obj.DOCUMENT_NODE;

}

function isObject(obj) {

return type(obj) == "object";

}

function isPlainObject(obj) {

return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype;

}

function likeArray(obj) {

return typeof obj.length == ‘number‘;

}

/**

* 字符串替换

* 使用replace第二个参数带回调

*/

function camelize(str) {

return str.replace(/-+(.)?/g,

function(match, chr) {

console.log(chr);

return chr ? chr.toUpperCase() : ‘‘;

}

);

}

function dasherize(str) {

return str.replace(/::/g, ‘/‘)

.replace(/([A-Z]+)([A-Z][a-z])/g, ‘$1_$2‘)

.replace(/([a-z\d])([A-Z])/g, ‘$1_$2‘)

.replace(/_/g, ‘-‘)

.toLowerCase()

}

function maybeAddPx(name, value) {

return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value;

}

/**

* `$.zepto.fragment`需要一个html字符串和一个可选标记名来生成dom

* 产生的dom返回一个数组形式

* 该功能可以被插件覆盖

* 没有覆盖所有浏览器

*/

zepto.fragment = function(html, name, properties) {

var dom;

var nodes;

var container;

// 标签特殊化处理

if (singleTagRE.test(html)) {

dom = $(document.createElement(RegExp.$1));

}

if (!dom) {

if (html.replace) {

html = html.replace(tagExpanderRE, "<$1></$2>");

}

if (name === undefined) {

name = fragmentRE.test(html) && RegExp.$1;

}

if (!(name in containers)) {

name = ‘*‘;

}

container = containers[name];

container.innerHTML = ‘‘ + html;

dom = $.each(slice.call(container.childNodes), function() {

container.removeChild(this);

});

}

if (isPlainObject(properties)) {

nodes = $(dom);

$.each(properties, function(key, value) {

if (methodAttributes.indexOf(key) > -1) {

nodes[key](value);

}

else {

nodes.attr(key, value);

}

});

}

return dom;

};

/**

* `$.zepto.Z`将给定`dom`节点数组的原型赋上`$.fn`提供的所有Zepto函数

* 请注意,`__proto__`不支持IE浏览器

*/

zepto.Z = function(dom, selector) {

dom = dom || [];

dom.__proto__ = $.fn;

dom.selector = selector || ‘‘;

return dom;

};

/**

* `$.zepto.isZ`检查给定的对象是一个Zepto的集合,可被插件覆盖

*/

zepto.isZ = function(object) {

return object instanceof zepto.Z;

};

/**

* `$.zepto.init`是Zepto借鉴jQuery的`$.fn.init`方法

* 采用css选择器和一个可选的上下文(处理各种特殊情况)

* 该方法可被插件覆盖

*/

zepto.init = function(selector, context) {

// 如果没有给出,返回一个空的Zepto集合

if (!selector) {

return zepto.Z();

}

// 检测字符串类型

else if (typeof selector == ‘string‘) {

selector = selector.trim();

/**

* 如果是一个HTML片段,创建节点注意,在chrome21和FF15版本,

* DOM错误12不是以<被抛出

*/

if (selector[0] == ‘<‘ && fragmentRE.test(selector)) {

dom = zepto.fragment(selector, RegExp.$1, context);

selector = null;

// 如果存在一个上下文环境,建立收集,并从中选择节点

} else if (context !== undefined) {

return $(context).find(selector);

// 如果是一个css选择器,用它来选择节点

} else {

dom = zepto.qsa(document, selector);

}

// 如果一个函数存在,在domready就绪后触发

} else if (isFunction(selector)) {

return $(document).ready(selector);

}

// 如果zepto已经收集给出,直接返回

else if (zepto.isZ(selector)) {

return selector;

} else {

// 如果节点已经为数组,进行聚合

if (isArray(selector)) {

dom = compact(selector);

}

// 包装DOM节点

else if (isObject(selector)) {

dom = [selector];

selector = null;

}

// 如果是一个HTML片段,对该片段创建节点

else if (fragmentRE.test(selector)) {

dom = zepto.fragment(selector.trim(), RegExp.$1, context);

selector = null;

}

// 如果存在上下文环境,先建立收集,并从中选择节点

else if (context !== undefined) {

return $(context).find(selector);

}

// 如果是一个css选择器,用它来选择节点

else {

dom = zepto.qsa(document, selector);

}

}

// 对发现的节点创建一个新的Zepto集合

return zepto.Z(dom, selector);

};

// `$`作为Zepto的元对象,当调用`$`该函数将转由`$.zepto.init`处理

$ = function(selector, context) {

return zepto.init(selector, context);

};

/**

* `$.zepto.qsa`是Zepto的css选择器,使用document.querySelectorAll及特殊情况

* 可被插件覆盖

*/

zepto.qsa = function(element, selector) {

var found;

var maybeID = (selector[0] == ‘#‘);

var maybeClass = !maybeID && selector[0] == ‘.‘;

// 确认下标从1开始后的字符串

var nameOnly = maybeID || maybeClass ? selector.slice(1) : selector;

var isSimple = simpleSelectorRE.test(nameOnly);

return (isDocument(element) && isSimple && maybeID) ?

((found = element.getElementById(nameOnly)) ? [found] : []) :

slice.call((isSimple && !maybeID) ?

maybeClass ? element.getElementsByClassName(nameOnly) : // class名称

element.getElementsByTagName(selector) : // tag名称

element.querySelectorAll(selector) // 查询所有匹配到的

);

};

/**

* $.contains(parent, node); 示例$.contains($(‘#test‘)[0], $(‘.aa‘)[0])

* 检查父节点是否包含给定的dom节点,如果两者是相同节点,返回false

* return {boolean} true/false

*/

$.contains = document.documentElement.contains ?

function (parent, node) {

return parent !== node && parent.contains(node);

} :

function (parent, node) {

while (node && (node = node.parentNode)) {

if (node === parent) {

return true;

}

}

return false;

};

function setAttribute(node, name, value) {

value == null ? node.removeAttribute(name) : node.setAttribute(name, value);

}

// 函数参数

function funcArg(context, arg, idx, payload) {

return isFunction(arg) ? arg.call(context, idx, payload) : arg;

}

$.type = type;

$.isFunction = isFunction;

$.isWindow = isWindow;

$.isArray = isArray;

$.isPlainObject = isPlainObject;

$.camelCase = camelize;

/**

* Zepto对象迭代器

* @param {object|array} elements 数据对象

* @param {function} callback 回调函数

* return {object|array} elements 数据对象

*/

$.each = function(elements, callback) {

var i;

var key;

// 数组检测

if (likeArray(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("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {

class2type["[object " + name + "]"] = name.toLowerCase();

});

/**

* 定义的方法,适用于所有的Zepto对象

*/

$.fn = {

ready: function(callback) {

// 检查document.body存在且文档渲染完成

if (readyRE.test(document.readyState) && document.body) {

callback($);

} else {

document.addEventListener(‘DOMContentLoaded‘, function() {

callback($);

}, false);

}

},

each: function(callback) {

emptyArray.every.call(this, function(el, idx) {

return callback.call(el, idx, el) !== false;

});

return this;

},

text: function(text) {

return 0 in arguments ?

this.each(function(idx) {

var newText = funcArg(this, text, idx, this.textContent);

this.textContent = (newText == null) ? ‘‘ : ‘‘ + newText;

}) :

(0 in this ? this[0].textContent : null);

},

attr: function(name, value) {

var result;

return (typeof name == ‘string‘ && !(1 in arguments)) ?

(!this.length || this[0].nodeType !== 1 ? undefined :

(!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result

) :

this.each(function(idx){

if (this.nodeType !== 1) {

return;

}

if (isObject(name)) {

for (key in name) {

setAttribute(this, key, name[key]);

}

} else {

setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)));

}

});

},

// css属性设置

css: function(property, value) {

if (arguments.length < 2) {

var element = this[0];

var computedStyle = getComputedStyle(element, ‘‘);

if (!element) {

return;

}

if (typeof property == ‘string‘) {

return element.style[camelize(property)] || computedStyle.getPropertyValue(property);

} else if (isArray(property)) {

var props = {};

$.each(isArray(property) ? property : [property], function(_, prop) {

props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop));

});

return props;

}

}

var css = ‘‘;

if (type(property) == ‘string‘) {

if (!value && value !== 0) {

this.each(function() {

this.style.removeProperty(dasherize(property));

});

} else {

css = dasherize(property) + ":" + maybeAddPx(property, value);

}

} else {

for (var key in property) {

if (!property[key] && property[key] !== 0) {

this.each(function() {

this.style.removeProperty(dasherize(key));

});

} else {

css += dasherize(key) + ‘:‘ + maybeAddPx(key, property[key]) + ";";

}

}

}

return this.each(function() {

this.style.cssText += ‘;‘ + css;

});

}

};

// 继承

zepto.Z.prototype = $.fn;

$.zepto = zepto;

return $;

})();

// 全局变量接口

window.Zepto = Zepto;

window.$ === undefined && (window.$ = Zepto);

浏览器输出结果:

时间: 11-02

Zepto源码分析之二~三个API的相关文章

[Android]Volley源码分析(二)

上一篇介绍了Volley的使用,主要接触了Request与RequestQueue这两个类,这篇就来了解一下这两个类的具体实现. Request类图: Request类: Request是一个抽象类,其中的主要属性: mMethod: 请求方法,目前支持GET, POST, PUT, DELETE, HEAD, OPTIONS,TRACE, PATCH方法 mUrl: 请求Url mErrorListener: 错误处理监听器,请求出错时调用 mSequence: 请求的序号,相同优先级的请求在

linux中断源码分析 - 中断发生(三)

本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 回顾 上篇文章linux中断源码分析 - 初始化(二)已经描述了中断描述符表和中断描述符数组的初始化,由于在初始化期间系统关闭了中断(通过设置CPU的EFLAGS寄存器的IF标志位为0),当整个中断和异常的初始化完成后,系统会开启中断(设置CPU的EFLAGS寄存器的IF标志位为1),此时整个系统的中断已经开始可以使用了.本篇文章我们具体研究一次典型中断发生时的运行流程. 中断产生 我们需要先明确一下,中断控

zepto源码分析系列

如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Zepto源码分析-event模块 Zepto源码分析-ajax模块 Zepto源码分析-form模块 Zepto源码分析-deferred模块 Zepto源码分析-动画(fx fx_method)模块 内容一定要200字一定要200字内容一定要200字一定要200字内容一定要200字一定要200字内容

Unity时钟定时器插件——Vision Timer源码分析之二

Unity时钟定时器插件--Vision Timer源码分析之二 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面的已经介绍了vp_Timer(点击前往查看),vp_TimeUtility相对简单很多,vp_TimeUtility定义了个表示时间的结构Units: C#代码   /// <summary> /// represents a time measured in standard units /// </summar

AndroidPn源码分析(二)

接上篇: (一)客户端与服务器建立连接 上一篇写到ClientSession createClientSession这里,创建一个客户端的session.在SessionManager类中创建了session之后,这里拼接了两个xml内容的text.一个是Build the start packet response,创建一个头条包,作为回应.另外一个是:XMPP 1.0 needs stream features,是xmpp1.0所需要的文件结构.两个消息的格式内容如下: <?xml vers

手机自动化测试:appium源码分析之bootstrap三

手机自动化测试:appium源码分析之bootstrap三 研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对appium进行定制,poptest在2015年10月24日开设appium的课程,课程采用真实的商业项目进行培训,用现在互联网金融的业务.bootstrap代码中io.appium.android.bootstrap.handler包中的类都是对应的指令类,核心都是execute方法. 下面我们看下Hash

Cordova Android源码分析系列二(CordovaWebView相关类分析)

本篇文章是Cordova Android源码分析系列文章的第二篇,主要分析CordovaWebView和CordovaWebViewClient类,通过分析代码可以知道Web网页加载的过程,错误出来,多线程处理等. CordovaWebView类分析 CordovaWebView类继承了Android WebView类,这是一个很自然的实现,共1000多行代码.包含了PluginManager pluginManager,BroadcastReceiver receiver,CordovaInt

区块链教程以太坊源码分析core-state-process源码分析(二)

兄弟连区块链教程以太坊源码分析core-state-process源码分析(二):关于g0的计算,在黄皮书上由详细的介绍和黄皮书有一定出入的部分在于if contractCreation && homestead {igas.SetUint64(params.TxGasContractCreation) 这是因为 Gtxcreate+Gtransaction = TxGasContractCreation func IntrinsicGas(data []byte, contractCre

zepto源码分析-代码结构【转载】

本来想学习一下jQuery的源码,但由于jQuery的源码有10000多行,设计相当复杂,所以决定从zepto开始,分析一个成熟的框架的代码结构及执行步骤. 网上也有很多zepto的源码分析,有的给源码添加注释,有的谈与jQuery的不同,但是都没有系统的讲解zepto框架的代码结构及初始化Zepto对象的过程. 准备 默认你已经对面向对象有一定的了解,本文是边实践边写的,虽有些乱,但好处是为大家提供了分析的思路. 英文文档. 中文文档 注意在文中$变量表示一个函数对象,而$()表示执行函数,他