Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api。 如果你会用jquery,那么你也会用zepto。
Zepto 中文手册:https://www.runoob.com/manual/zeptojs.html
/* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */
;(function(undefined) {
if (String.prototype.trim === undefined) // fix for iOS 3.2
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '')
}
// For iOS 3.x
// from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
//这个方法的作用就是累似一个累计处理的作用,将前一条数据的处理结果用作下一次的处理
//比如[1,2,3,4,].reduce(function(x,y){ return x+y}); ==> ((1+2)+3)+4,
if (Array.prototype.reduce === undefined) Array.prototype.reduce = function(fun) {
if (this === void 0 || this === null) throw new TypeError()
var t = Object(this),
len = t.length >>> 0,
k = 0,
accumulator
if (typeof fun != 'function') throw new TypeError()
if (len == 0 && arguments.length == 1) throw new TypeError()
//取初始值
if (arguments.length >= 2) accumulator = arguments[1] //如果参数长度大于2个,则将第二个参数作为初始值
else do {
if (k in t) {
accumulator = t[k++] //否则将数组的第一条数据作为初绍值
break
}
if (++k >= len) throw new TypeError() //什么情况下会执行到这里来???
} while (true)
//遍历数组,将前一次的结果传入处理函数进行累计处理
while (k < len) {
if (k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
k++
}
return accumulator
}
})()
var Zepto = (function() {
var undefined, key, $, classList, emptyArray = [],
slice = emptyArray.slice,
filter = emptyArray.filter,
document = window.document,
elementDisplay = {}, classCache = {},
getComputedStyle = document.defaultView.getComputedStyle,
//设置CSS时,不用加px单位的属性
cssNumber = {
'column-count': 1,
'columns': 1,
'font-weight': 1,
'line-height': 1,
'opacity': 1,
'z-index': 1,
'zoom': 1
},
//HTML代码片断的正则
fragmentRE = /^\s*<(\w+|!)[^>]*>/,
//匹配非单独一个闭合标签的标签,类似将<div></div>写成了<div/>
tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
//根节点
rootNodeRE = /^(?:body|html)$/i,
//需要提供get和set的方法名
// special attributes that should be get/set via method calls
methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
//相邻节点的一些操作
adjacencyOperators = ['after', 'prepend', 'before', 'append'],
table = document.createElement('table'),
tableRow = document.createElement('tr'),
//这里的用途是当需要给tr,tbody,thead,tfoot,td,th设置innerHTMl的时候,需要用其父元素作为容器来装载HTML字符串
containers = {
'tr': document.createElement('tbody'),
'tbody': table,
'thead': table,
'tfoot': table,
'td': tableRow,
'th': tableRow,
'*': document.createElement('div')
},
//当DOM ready的时候,document会有以下三种状态的一种
readyRE = /complete|loaded|interactive/,
//class选择器的正则
classSelectorRE = /^\.([\w-]+)$/,
//id选择器的正则
idSelectorRE = /^#([\w-]*)$/,
//DOM标签正则
tagSelectorRE = /^[\w-]+$/,
class2type = {},
toString = class2type.toString,
zepto = {},
camelize, uniq,
tempParent = document.createElement('div');
//判断一个元素是否匹配给定的选择器
zepto.matches = function(element, selector) {
if (!element || element.nodeType !== 1) return false
//引用浏览器提供的MatchesSelector方法
var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector
if (matchesSelector) return matchesSelector.call(element, selector);
//如果浏览器不支持MatchesSelector方法,则将节点放入一个临时div节点,
//再通过selector来查找这个div下的节点集,再判断给定的element是否在节点集中,如果在,则返回一个非零(即非false)的数字
// fall back to performing a selector:
var match, parent = element.parentNode,temp = !parent
//当element没有父节点,那么将其插入到一个临时的div里面
if (temp)(parent = tempParent).appendChild(element)
//将parent作为上下文,来查找selector的匹配结果,并获取element在结果集的索引,不存在时为-1,再通过~-1转成0,存在时返回一个非零的值
match = ~zepto.qsa(parent, selector).indexOf(element)
//将插入的节点删掉
temp && tempParent.removeChild(element)
return match
}
//获取对象类型
function type(obj) {
//obj为null或者undefined时,直接返回'null'或'undefined'
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"
}
//对于通过字面量定义的对象和new Object的对象返回true,new Object时传参数的返回false
//可参考http://snandy.iteye.com/blog/663245
function isPlainObject(obj) {
return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
}
function isArray(value) {
return value instanceof Array
}
//类数组,比如nodeList,这个只是做最简单的判断,如果给一个对象定义一个值为数据的length属性,它同样会返回true
function likeArray(obj) {
return typeof obj.length == 'number'
}
//清除给定的参数中的null或undefined,注意0==null,'' == null为false
function compact(array) {
return filter.call(array, function(item) {
return item != null
})
}
//类似得到一个数组的副本
function flatten(array) {
return array.length > 0 ? $.fn.concat.apply([], array) : array
}
//将字符串转成驼峰式的格式
camelize = function(str) {
return str.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : ''
})
}
//将字符串格式化成-拼接的形式,一般用在样式属性上,比如border-width
function dasherize(str) {
return str.replace(/::/g, '/') //将::替换成/
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') //在大小写字符之间插入_,大写在前,比如AAAbb,得到AA_Abb
.replace(/([a-z\d])([A-Z])/g, '$1_$2') //在大小写字符之间插入_,小写或数字在前,比如bbbAaa,得到bbb_Aaa
.replace(/_/g, '-') //将_替换成-
.toLowerCase() //转成小写
}
//数组去重,如果该条数据在数组中的位置与循环的索引值不相同,则说明数组中有与其相同的值
uniq = function(array) {
return filter.call(array, function(item, idx) {
return array.indexOf(item) == idx
})
}
//将给定的参数生成正则
function classRE(name) {
//classCache,缓存正则
return name in classCache ? classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
}
//给需要的样式值后面加上'px'单位,除了cssNumber里面的指定的那些
function maybeAddPx(name, value) {
return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
}
//获取节点的默认display属性
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" && (display = "block") //当display等于none时,设置其值为block,搞不懂为毛要这样
elementDisplay[nodeName] = display //缓存元素的默认display属性
}
return elementDisplay[nodeName]
}
//获取指定元素的子节点(不包含文本节点),Firefox不支持children,所以只能通过筛选childNodes
function children(element) {
return 'children' in element ? slice.call(element.children) : $.map(element.childNodes, function(node) {
if (node.nodeType == 1) return node
})
}
// `$.zepto.fragment` takes a html string and an optional tag name
// to generate DOM nodes nodes from the given html string.
// The generated DOM nodes are returned as an array.
// This function can be overriden in plugins for example to make
// it compatible with browsers that don't support the DOM fully.
zepto.fragment = function(html, name, properties) {
//将类似<div class="test"/>替换成<div class="test"></div>,算是一种修复吧
if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
//给name取标签名
if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
//设置容器标签名,如果不是tr,tbody,thead,tfoot,td,th,则容器标签名为div
if (!(name in containers)) name = '*'
var nodes, dom, container = containers[name] //创建容器
container.innerHTML = '' + html //将html代码片断放入容器
//取容器的子节点,这样就直接把字符串转成DOM节点了
dom = $.each(slice.call(container.childNodes), function() {
container.removeChild(this) //逐个删除
})
//如果properties是对象, 则将其当作属性来给添加进来的节点进行设置
if (isPlainObject(properties)) {
nodes = $(dom) //将dom转成zepto对象,为了方便下面调用zepto上的方法
//遍历对象,设置属性
$.each(properties, function(key, value) {
//如果设置的是'val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset',则调用zepto上相对应的方法
if (methodAttributes.indexOf(key) > -1) nodes[key](value)
else nodes.attr(key, value)
})
}
//返回将字符串转成的DOM节点后的数组,比如'<li></li><li></li><li></li>'转成[li,li,li]
return dom
}
// `$.zepto.Z` swaps out the prototype of the given `dom` array
// of nodes with `$.fn` and thus supplying all the Zepto functions
// to the array. Note that `__proto__` is not supported on Internet
// Explorer. This method can be overriden in plugins.
zepto.Z = function(dom, selector) {
dom = dom || []
dom.__proto__ = $.fn //通过给dom设置__proto__属性指向$.fn来达到继承$.fn上所有方法的目的
dom.selector = selector || ''
return dom
}
// `$.zepto.isZ` should return `true` if the given object is a Zepto
// collection. This method can be overriden in plugins.
//判断给定的参数是否是Zepto集
zepto.isZ = function(object) {
return object instanceof zepto.Z
}
// `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
// takes a CSS selector and an optional context (and handles various
// special cases).
// This method can be overriden in plugins.
zepto.init = function(selector, context) {
// If nothing given, return an empty Zepto collection
if (!selector) return zepto.Z() //没有参数,返回空数组
//如果selector是个函数,则在DOM ready的时候执行它
else if (isFunction(selector)) return $(document).ready(selector)
//如果selector是一个zepto.Z实例,则直接返回它自己
else if (zepto.isZ(selector)) return selector
else {
var dom
//如果selector是一个数组,则将其里面的null,undefined去掉
if (isArray(selector)) dom = compact(selector)
//如果selector是个对象,注意DOM节点的typeof值也是object,所以在里面还要再进行一次判断
else if (isObject(selector))
//如果是申明的对象,如{}, 则将selector属性copy到一个新对象,并将结果放入数组
//如果是该对象是DOM,则直接放到数组中
dom = [isPlainObject(selector) ? $.extend({}, selector) : selector], selector = null
//如果selector是一段HTML代码片断,则将其转换成DOM节点
else if (fragmentRE.test(selector)) dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
//如果存在上下文context,则在上下文中查找selector,此时的selector为普通的CSS选择器
else if (context !== undefined) return $(context).find(selector)
//如果没有给定上下文,则在document中查找selector,此时的selector为普通的CSS选择器
else dom = zepto.qsa(document, selector)
//最后将查询结果转换成zepto集合
return zepto.Z(dom, selector)
}
}
// `$` will be the base `Zepto` object. When calling this
// function just call `$.zepto.init, which makes the implementation
// details of selecting nodes and creating Zepto collections
// patchable in plugins.
$ = function(selector, context) {
return zepto.init(selector, context)
}
//扩展,deep表示是否深度扩展
function extend(target, source, deep) {
for (key in source)
//如果深度扩展
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
//如果要扩展的数据是对象且target相对应的key不是对象
if (isPlainObject(source[key]) && !isPlainObject(target[key])) target[key] = {}
//如果要扩展的数据是数组且target相对应的key不是数组
if (isArray(source[key]) && !isArray(target[key])) target[key] = []
extend(target[key], source[key], deep)
} else if (source[key] !== undefined) target[key] = source[key]
}
// Copy all but undefined properties from one or more
// objects to the `target` object.
$.extend = function(target) {
var deep, args = slice.call(arguments, 1)
if (typeof target == 'boolean') { //当第一个参数为boolean类型的值时,表示是否深度扩展
deep = target
target = args.shift() //target取第二个参数
}
//遍历后面的参数,全部扩展到target上
args.forEach(function(arg) {
extend(target, arg, deep)
})
return target
}
// `$.zepto.qsa` is Zepto's CSS selector implementation which
// uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
// This method can be overriden in plugins.
zepto.qsa = function(element, selector) {
var found
//当element为document,且selector为ID选择器时
return (isDocument(element) && idSelectorRE.test(selector)) ?
//直接返回document.getElementById,RegExp.$1为ID的值,当没有找节点时返回[]
((found = element.getElementById(RegExp.$1)) ? [found] : []) :
//当element不为元素节点或者document时,返回[]
(element.nodeType !== 1 && element.nodeType !== 9) ? [] :
//否则将获取到的结果转成数组并返回
slice.call(
//如果selector是标签名,直接调用getElementsByClassName
classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
//如果selector是标签名,直接调用getElementsByTagName
tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
//否则调用querySelectorAll
element.querySelectorAll(selector))
}
//在结果中进行过滤
function filtered(nodes, selector) {
return selector === undefined ? $(nodes) : $(nodes).filter(selector)
}
//判断parent是否包含node
$.contains = function(parent, node) {
return parent !== node && parent.contains(node)
}
//这个函数在整个库中取着很得要的作用,处理arg为函数或者值的情况
//下面很多设置元素属性时的函数都有用到
function funcArg(context, arg, idx, payload) {
return isFunction(arg) ? arg.call(context, idx, payload) : arg
}
function setAttribute(node, name, value) {
//如果设置的值为null或undefined,则相当于删除该属性,否则设置name属性为value
value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
}
// access className property while respecting SVGAnimatedString
function className(node, value) {
var klass = node.className,
svg = klass && klass.baseVal !== undefined
if (value === undefined) return svg ? klass.baseVal : klass
svg ? (klass.baseVal = value) : (node.className = value)
}
// "true" => true
// "false" => false
// "null" => null
// "42" => 42
// "42.5" => 42.5
// JSON => parse if valid
// String => self
function deserializeValue(value) {
var num
try {
return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value
} catch (e) {
return value
}
}
$.type = type
$.isFunction = isFunction
$.isWindow = isWindow
$.isArray = isArray
$.isPlainObject = isPlainObject
//空对象
$.isEmptyObject = function(obj) {
var name
for (name in obj) return false
return true
}
//获取指定的值在数组中的位置
$.inArray = function(elem, array, i) {
return emptyArray.indexOf.call(array, elem, i)
}
//将字符串转成驼峰式的格式
$.camelCase = camelize
//去字符串头尾空格
$.trim = function(str) {
return str.trim()
}
// plugin compatibility
$.uuid = 0
$.support = {}
$.expr = {}
//遍历elements,将每条记录放入callback里进宪处理,保存处理函数返回值不为null或undefined的结果
//注意这里没有统一的用for in,是为了避免遍历数据默认属性的情况,如数组的toString,valueOf
$.map = function(elements, callback) {
var value, values = [],
i, key
//如果被遍历的数据是数组或者nodeList
if (likeArray(elements)) for (i = 0; i < elements.length; i++) {
value = callback(elements[i], i)
if (value != null) values.push(value)
} else
//如果是对象
for (key in elements) {
value = callback(elements[key], key)
if (value != null) values.push(value)
}
return flatten(values)
}
//遍历数组,将每条数据作为callback的上下文,并传入数据以及数据的索引进行处理,如果其中一条数据的处理结果明确返回false,
//则停止遍历,并返回elements
$.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
}
//过滤
$.grep = function(elements, callback) {
return filter.call(elements, callback)
}
if (window.JSON) $.parseJSON = JSON.parse
// Populate the class2type map
//填充class2type的值

被折叠的 条评论
为什么被折叠?



