$.each:

/**
* 以集合每一个元素作为上下文,来执行回调函数
* @param elements
* @param callback
* @returns {*}
*/
$.each = function(elements, callback){
var i, 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
}

这里的elements可以是数组或者对象,如果是对象,则会将其原型里面的属性也遍历出来,最后返回elments本身,如果回调函数返回了false,则终止循环

remove:

/**
* 删除元素集
* 原理 parentNode.removeChild
* @returns {*}
*/
remove: function(){
//遍历到其父元素 removeChild
return this.each(function(){
if (this.parentNode != null)
this.parentNode.removeChild(this)
})
},

这里的重点是parentNode.removeChild(this); 如果是没有父节点的这里不会执行。

is:

//返回集合中的第1条记录是否与selector匹配
is: function(selector){
return this.length > 0 && zepto.matches(this[0], selector)
}

例如$("#id").is(".hasClass"); 实际就是调用matches进行匹配

not: 

//排除集合里满足条件的记录,接收参数为:css选择器,function, dom ,nodeList
not: function(selector){
var nodes=[]
//当selector为函数时,safari下的typeof nodeList也是function,所以这里需要再加一个判断selector.call !== undefined
if (isFunction(selector) && selector.call !== undefined)
this.each(function(idx){
//注意这里收集的是selector.call(this,idx)返回结果为false的时候记录
if (!selector.call(this,idx)) nodes.push(this)
})
else {
//当selector为字符串的时候,对集合进行筛选,也就是筛选出集合中满足selector的记录
var excludes = typeof selector == 'string' ? this.filter(selector) :
//当selector为nodeList时执行slice.call(selector),注意这里的isFunction(selector.item)是为了排除selector为数组的情况
//当selector为css选择器,执行$(selector)
(likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector);
this.forEach(function(el){
//筛选出不在excludes集合里的记录,达到排除的目的
if (excludes.indexOf(el) < 0) nodes.push(el)
})
}
return $(nodes)//由于上面得到的结果是数组,这里需要转成zepto对象,以便继承其它方法,实现链写
},

这里首先判断selector是否为函数,如果是,则遍历执行函数,如果返回false,则push到数组中

如果css选择字符串则调用this.filter(seelctor),这里有个小技巧使得not和filter相互调用

如果是数组或对象,则直接返回$(他自己)

最后遍历this,只要不是在excludes里面的都是满足条件的

has:

/*
接收node和string作为参数,给当前集合筛选出包含selector的集合
isObject(selector)是判断参数是否是node,因为typeof node == 'object'
当参数为node时,只需要判读当前记当里是否包含node节点即可
当参数为string时,则在当前记录里查询selector,如果长度为0,则为false,filter函数就会过滤掉这条记录,否则保存该记录
*/
has: function(selector){
return this.filter(function(){
return isObject(selector) ?
$.contains(this, selector) :
$(this).find(selector).size()
})
},

重点提示下:这里的this如果也满足selector,则最后返回的结果集里也会有this  

show:

 
/**
* 获取元素的默认display属性
* 是为了兼容什么?
* @param nodeName
* @returns {*}
*/
function defaultDisplay(nodeName) {
var element, display
if (!elementDisplay[nodeName]) { //缓存里没有 element = document.createElement(nodeName)
document.body.appendChild(element)
display = getComputedStyle(element, '').getPropertyValue("display")
element.parentNode.removeChild(element) // display == "none",设置成blaock,即隐藏-显示
display == "none" && (display = "block") elementDisplay[nodeName] = display //TODO:缓存元素的默认display属性,缓存干嘛?
}
return elementDisplay[nodeName]
}

/**
* 展示
* @returns {*}
*/
show: function(){
return this.each(function(){
//清除内联样式display="none"
this.style.display == "none" && (this.style.display = '')
//计算样式display为none时,重赋显示值
if (getComputedStyle(this, '').getPropertyValue("display") == "none")
this.style.display = defaultDisplay(this.nodeName)
//defaultDisplay是获取元素默认display的方法
})
},

this.style.display = ' '是清除元素的style里面的display样式,恢复元素的默认样式。

getComputedStyle(dom)能获取dom的所有css样式,第二个参数可以不传

getComputedStyle(dom,":after")能获取dom的:after伪类的所有css样式(这里只谈移动端)

详情请看:http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/

如果清除了style里面的display属性还是无效的话,直接显式的给display赋默认值,defaultDisplay的内部实际是在document里面新添加一个元素,来获取默认值的。

css:

/**
* 读写样式 写:内联样式 读:计算样式
* 原理 读:elment[style]/getComputedStyle, 写 this.style.cssText 行内样式设值
* @param property String/Array/Fun
* @param value
* @returns {*}
*/
css: function(property, value){
//只有一个传参,读
if (arguments.length < 2) {
var computedStyle, element = this[0]
if(!element) return
//getComputedStyle是一个可以获取当前元素所有最终使用的CSS属性值。返回的是一个CSS样式声明对象([object CSSStyleDeclaration]),只读
//读到计算样式
computedStyle = getComputedStyle(element, '')
//设置样式
if (typeof property == 'string')// 字符串
//优先读行内样式,再读计算样式,行内样式级别最高? TODO:似乎有bug,如果设置了!important 呢
return element.style[camelize(property)] || computedStyle.getPropertyValue(property)
else if (isArray(property)) { //数组
var props = {}
$.each(property, function(_, prop){ //遍历读取每一条样式,存入JSON,返回
props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))
})
return props
}
} //如果是写
var css = ''
if (type(property) == 'string') {
if (!value && value !== 0) //null,undefined时,删掉样式
this.each(function(){
//删除 dasherize是将字符串转换成css属性(background-color格式)
this.style.removeProperty(dasherize(property))
})
else
//‘-’格式值 + px单位
css = dasherize(property) + ":" + maybeAddPx(property, value)
} else {
for (key in property) //是对象时
if (!property[key] && property[key] !== 0)
//当property[key]的值为null/undefined,删除属性
this.each(function(){ this.style.removeProperty(dasherize(key)) })
else
//‘-’格式值 + px单位
css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
} //设值 //TODO: this.style.cssText += 未考虑去重了
return this.each(function(){ this.style.cssText += ';' + css })
},

判断只传了一个参数:arguments.length < 2 或者 1 in  arguments,

流程大致如下:

1:判断参数,如果是一个参数则为只读模式

1.2:如果property为字符串,则 直接获取元素的css属性值

1.3:如果property为数组,则this.each遍历数组,获取每个属性的value值并形成props对象返回

2:若有2个参数,为写模式

2.1:如果property为字符串,则style.cssText+= property:value(这里的处理没有去重,但本人测了一下,这并不影响页面的渲染)

2.2:如果property为对象,则循环遍历property

这里有几个函数要提一下:

camelize() 将带“—”的转为驼峰命名例如“background-color”转为“backgroundColor”,对象属性是必须驼峰命名的。

dasherize()  将“backgroundColor”转为“background-color”,内部实现是用正则表达式匹配

style.removeProperty  删除style中的某个属性

style.setProperty(property,value,priority)  设置style中的某个属性,priority可取“important” ,(不太明白为什么zepto不用这个方法,望高人指教)

maybeAddPx (property,value):根据property类型给value加上“px”后缀

html:


/**
* 处理 arg为函数/值
* 为函数,返回函数返回值
* 为值,返回值
* @param context
* @param arg
* @param idx
* @param payload
* @returns {*}
*/
function funcArg(context, arg, idx, payload) {
return isFunction(arg) ? arg.call(context, idx, payload) : arg
}
/**
* 读写元素HTML内容
* 原理 通过innerHTML读内容,append()写内容
* @param html
* @returns {*|string|string|string|string|string}
*/
html: function(html){
return in arguments ?
this.each(function(idx){
var originHtml = this.innerHTML //记录原始的innerHTMl
//如果参数html是字符串直接插入到记录中,
//如果是函数,则将当前记录作为上下文,调用该函数,且传入该记录的索引和原始innerHTML作为参数
$(this).empty().append( funcArg(this, html, idx, originHtml) )
}) :
( in this ? this[].innerHTML : null)
},

html():不传参数则获取元素的innerHTML,

html("<div></div>"):设置元素的innerHTML

html(function(){....}):可传入方法,返回值设置为元素的innerHTML

这里的funcArg的功能是判断html为函数则以this为上下文,以idx,originHtml为参数执行函数

text:

/**
* 读写元素文本内容
* 原理: 通过 textContent 读写文本
* @param text
* @returns {*}
*/
text: function(text){
return in arguments ?
this.each(function(idx){ //传参遍历写入
var newText = funcArg(this, text, idx, this.textContent)
this.textContent = newText == null ? '' : ''+newText
}) :
( in this ? this[].textContent : null) //未传参读
},

  




												

zepto源码研究 - zepto.js-4(常用的工具)的更多相关文章

  1. zepto源码研究 - zepto.js - 1

    简要:网上已经有很多人已经将zepto的源码研究得很细致了,但我还是想写下zepto源码系列,将别人的东西和自己的想法写下来以加深印象也是自娱自乐,文章中可能有许多错误,望有人不吝指出,烦请赐教. 首 ...

  2. zepto源码研究 - deferred.js(jquery-deferred.js)

    简要:zepto的deferred.js 并不遵守promise/A+ 规范,而在jquery v3.0.0中的defer在一定程度上实现了promise/A+ ,因此本文主要研究jquery v3. ...

  3. zepto源码研究 - fx_methods.js

    简要:依赖fx.js,主要是针对show,hide,fadeIn,fadeOut的封装. 源码如下: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zept ...

  4. zepto源码研究 - fx.js

    简要:zepto 提供了一个基础方法animate来方便我们运用css动画.主要针对transform,animate以及普通属性(例如left,right,height,width等等)的trans ...

  5. zepto源码研究 - zepto.js (zepto.init)

    简要:当我们用$()时,便会直接调用zepto.init 生成zepto对象,那zepto.init是如何根据不同类型的参数来生产指定对象呢? zepto.init = function(select ...

  6. zepto源码研究 - zepto.js - 6(模板方法)

    width  height  模板方法   读写width/height ['width', 'height'].forEach(function(dimension){ //将width,hegih ...

  7. zepto源码研究 - ajax.js($.ajax具体流程分析)

    简要:$.ajax是zepto发送请求的核心方法,$.get,$.post,$.jsonp都是封装了$.ajax方法.$.ajax将jsonp与异步请求的代码格式统一起来,内部主要是先处理url,数据 ...

  8. zepto源码研究 - ajax.js($.ajaxJSONP 的分析)

    简要:jsonp是一种服务器和客户端信息传递方式,一般是利用script元素赋值src来发起请求.一般凡是带有src属性的元素发起的请求都是可以跨域的. 那么jsonp是如何获取服务器的数据的呢? j ...

  9. zepto源码研究 - zepto.js - 5(dom属性管理)

    index: $.fn = {...... indexOf: emptyArray.indexOf,} index: function(element){ //这里的$(element)[0]是为了将 ...

随机推荐

  1. Swift互用性:采用Cocoa设计模式(Swift 2.0版)-b

    本页包含内容: 委托(Delegation) 错误处理(Error Handling) 键值观察(Key-Value Observing) Target-Action模式(Target-Action) ...

  2. KeilMDK4.7a下载地址/中文乱码解决/自动关联设置

    推荐地址1,速度更快(确定为4.7a版本,且含注册机):1.http://www.mcuzone.com/software/keil/MDK470.RAR 2.http://kuai.xunlei.c ...

  3. cursor pin S wait on X

    cursor pin S wait on X: 这是10.2版本提出的mutex(互斥)机制用来解决library cache bin latch争夺问题引入的新事件,是否使用这种机制受到隐含参数_k ...

  4. 【HDOJ】5017 Ellipsoid

    简单地模拟退火. /* 5017 */ #include <cstdio> #include <cstring> #include <cstdlib> #inclu ...

  5. BZOJ1511: [POI2006]OKR-Periods of Words

    1511: [POI2006]OKR-Periods of Words Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 174  Solved: 92[Su ...

  6. http://blog.163.com/db_teacher/blog/static/194540298201110723712407/

    实验(七).第五章 数据库完整性 2011-11-07 14:37:12|  分类: 默认分类 |  标签: |字号大中小 订阅     一.实验目的 1.熟悉通过SQL语句对数据进行完整性控制 2. ...

  7. adb shell am pm 用法

    Using activity manager (am) Within an adb shell, you can issue commands with the activity manager (a ...

  8. linux系统目录介绍

    目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - /bin 该目录存放着系统最常用的最重要的命令,相当于DOS ...

  9. 判断一个js对象,是否具有某个属性

    一个对象,想必我们关注的最多的应该是它上面的属性有哪些吧.那么,怎么判断一个对象是否具有某个属性呢? /*下面是一个对比,看看在判断是否包括一个键上面,Object结构和Set结构的写法不同.*/ / ...

  10. 解决git提交问题error: The requested URL returned error: 403 Forbidden while accessing

    git提交代码时,出现这个错误"error: The requested URL returned error: 403 Forbidden while accessing https&qu ...